РЭДЛАЙН
Лучшие решения для Вас и Вашего бизнеса!
На нашем сайте вы можете получить информацию о веб-разработке, обслуживании и продвижении сайта. Интернет-маркетинге. SEO (поисковой оптимизации). Контекстной и медийной рекламе в Интернете. SMM. Регистрации доменов и хостинговых услугах. И современном дизайне сайтов. Вообщем того что касается веб-разработки, а также много другой полезной информации из мира интернета, бизнеса и интернет-технологий...
Создаем доступные и современные сайты, которые работают! Обслуживаем и эффективно продвигаем интернет-проекты с 2006 года!
Главная Блоги Пишем упаковщик по шагам. Шаг четвертый. Запускаем.


Пишем упаковщик по шагам. Шаг четвертый. Запускаем.

Предыдущий шаг: здесь.

Появилась новая версия библиотеки для работы с PE-файлами (0.1.4). Перекачайте и пересоберите ее.

Итак, из прошлых шагов мы имеем работающий упаковщик и базовый распаковщик, который пока что ничего не делает. В этом шаге мы добьемся запуска простых упакованных программ (которые не имеют ничего, кроме таблицы импорта и, возможно, релокаций). Первое, что нужно сделать в распаковщике помимо разархивирования данных - это поправить таблицу импорта оригинального файла. Обычно это делает загрузчик, но сейчас для сжатого файла роль загрузчика играем мы.

Добавим несколько полей в нашу структуру packed_file_info:

//Структура, хранящая информацию об упакованном файлеstruct packed_file_info
{
  BYTE number_of_sections;//Количество секций в оригинальном файле
  DWORD size_of_packed_data;//Размер упакованных данных
  DWORD size_of_unpacked_data;//Размер оригинальных данных
 
  DWORD total_virtual_size_of_sections;//Полный виртуальный размер всех секций оригинального файла
  DWORD original_import_directory_rva;//Относительный адрес оригинальной таблицы импорта
  DWORD original_import_directory_size;//Размер оригинальной таблицы импорта
  DWORD original_entry_point;//Оригинальная точка входа
 
  DWORD load_library_a;//Адрес процедуры LoadLibraryA из kernel32.dll
  DWORD get_proc_address;//Адрес процедуры GetProcAddress из kernel32.dll
  DWORD end_of_import_address_table;//Конец IAT};

Мы добавили 4 поля, которые нам пригодятся в распаковщике. Теперь необходимо их заполнить в коде упаковщика:

//...//Структура базовой информации о PE-файле
    packed_file_info basic_info ={0};//Получаем и сохраняем изначальное количество секций
    basic_info.number_of_sections= sections.size();
 
    //Запоминаем относительный адрес и размер//оригинальной таблицы импорта упаковываемого файла
    basic_info.original_import_directory_rva= image.get_directory_rva(IMAGE_DIRECTORY_ENTRY_IMPORT);
    basic_info.original_import_directory_size= image.get_directory_size(IMAGE_DIRECTORY_ENTRY_IMPORT);//Запоминаем его точку входа
    basic_info.original_entry_point= image.get_ep();//Запоминаем общий виртуальный размер всех секций//упаковываемого файла
    basic_info.total_virtual_size_of_sections= image.get_size_of_image();

Здесь все просто. Во втором уроке, если вы помните, я вручную считал общий виртуальный размер всех секций исходного файла и пояснял, что он эквивалентен значению, возвращаемому функцией get_size_of_image. Здесь мы этим воспользовались. С упаковщиком на этом все. Переходим к распаковщику (проект unpacker). Нам необходимо вкомпилировать в него алгоритм разархивирования LZO1Z. Я сделал просто и по-тупому - перенес в проект unpacker все файлы, необходимые для компиляции функции lzo1z_decompress (а именно, lzo1z_d1.c, lzo1x_d.ch, config1z.h, config1x.h, lzo_conf.h, lzo_ptr.h, lzo1_d.ch, miniacc.h). Кроме того, я прописал дополнительную include-директорию в проект: ../../lzo-2.06/include. Далее пришлось еще поковыряться с настройками проекта. Visual C++ при использовании функций memset, memcpy и подобных (а мы их использовать будем не раз) может по своему желанию встроить в получившийся exe-файл целую CRT, которая для нас совершенно лишняя. Пришлось отключить intrinsic (внутренние) функции (C/C++ - Optimization - Enable Intrinsic Functions - No) и полную оптимизацию (C/C++ - Optimization - Whole Program Optimization - No), на всякий случай добавить libcmt.lib в список игнорируемых библиотек (Linker - Input - Ignore Specific Default Libraries - libcmt.lib) и отключить генерацию кода на этапе линкования (Linker - Optimization - Link Time Code Generation - Default). А раз мы отключили все внутренние функции (среди них memset и memcpy), нам теперь нужна их собственная имплементация. Добавим два файла к проекту: memcpy.c и memset.c. В эти файлы я скопировал исходный код одноименных функций из CRT:

void* __cdecl memset(void*dst,
        int val,
        unsignedint count
        ){void*start = dst;
 
        while(count--){*(char*)dst =(char)val;
                dst =(char*)dst +1;}
 
        return(start);}
void* __cdecl memcpy(void* dst,
        constvoid* src,
        unsignedint count
        ){void* ret = dst;
 
        /*
         * copy from lower addresses to higher addresses
         */while(count--){*(char*)dst =*(char*)src;
                dst =(char*)dst +1;
                src =(char*)src +1;}
 
        return(ret);}

Нас поджидает еще одна проблема. У нас в коде теперь аж четыре модуля (четыре файла с исходным кодом, .c и .cpp), то после компиляции мы будем иметь четыре объектных (obj) файла. Далее линкер должен все это как-то слепить в единый exe-файл, и он это сделает. Но он расположит эти модули в exe-файле в одному ему известном порядке. Нам же необходимо, чтобы функция unpacker_main располагалась в самом начале кода распаковщика. Мы ведь ее в упаковщике патчим, помните? Эта проблема легко решается. Создадим текстовый файл с таким содержанием:

unpacker_main@0
lzo1z_decompress
memset
memcpy

Назовем его link_order.txt и расположим его в папке с исходниками проекта unpacker. Этот файл скажет линкеру, в каком порядке должны располагаться функции в результирующем файле. Укажем этот файл в настройках проекта: Linker - Optimization - Function Order - link_order.txt. Все, с настройками покончено, начинаем писать код распаковщика!

Во-первых, я увеличил количество данных, выделяемых на стеке до 256 байтов (sub esp, 256). Переменных локальных много, поэтому перестрахуемся, а то вдруг 128 не хватит.

Пропишем прототип функции распаковки в начало файла unpacker.cpp:

//Алгоритм распаковки#include "lzo_conf.h"/* decompression */
LZO_EXTERN(int)
lzo1z_decompress        (const lzo_bytep src, lzo_uint  src_len,
                                lzo_bytep dst, lzo_uintp dst_len,
                                lzo_voidp wrkmem /* NOT USED */);

Теперь мы сможем ее использовать в коде. Далее нам понадобятся функции VirtualAlloc (для выделения памяти), VirtualProtect (для изменения атрибутов страниц памяти) и VirtualFree (для освобождения выделенной памяти). Давайте импортируем их из kernel32.dll:

//kernel32.dll*reinterpret_cast<DWORD*>(&buf[0])='nrek';*reinterpret_cast<DWORD*>(&buf[4])='23le';*reinterpret_cast<DWORD*>(&buf[8])='lld.';*reinterpret_cast<DWORD*>(&buf[12])=0;
 
  //Загружаем библиотеку kernel32.dll
  HMODULE kernel32_dll;
  kernel32_dll = load_library_a(buf);
 
  //Тайпдеф прототипа функции VirtualAlloctypedef LPVOID (__stdcall* virtual_alloc_func)(LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect);//Тайпдеф прототипа функции VirtualProtecttypedef LPVOID (__stdcall* virtual_protect_func)(LPVOID lpAddress, SIZE_T dwSize, DWORD flNewProtect, PDWORD lpflOldProtect);//Тайпдеф прототипа функции VirtualFreetypedef LPVOID (__stdcall* virtual_free_func)(LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType);
 
  //VirtualAlloc*reinterpret_cast<DWORD*>(&buf[0])='triV';*reinterpret_cast<DWORD*>(&buf[4])='Alau';*reinterpret_cast<DWORD*>(&buf[8])='coll';*reinterpret_cast<DWORD*>(&buf[12])=0;
 
  //Получаем адрес функции VirtualAlloc
  virtual_alloc_func virtual_alloc;
  virtual_alloc =reinterpret_cast<virtual_alloc_func>(get_proc_address(kernel32_dll, buf));
 
  //VirtualProtect*reinterpret_cast<DWORD*>(&buf[0])='triV';*reinterpret_cast<DWORD*>(&buf[4])='Plau';*reinterpret_cast<DWORD*>(&buf[8])='etor';*reinterpret_cast<DWORD*>(&buf[12])='tc';
 
  //Получаем адрес функции VirtualProtect
  virtual_protect_func virtual_protect;
  virtual_protect =reinterpret_cast<virtual_protect_func>(get_proc_address(kernel32_dll, buf));
 
  //VirtualFree*reinterpret_cast<DWORD*>(&buf[0])='triV';*reinterpret_cast<DWORD*>(&buf[4])='Flau';*reinterpret_cast<DWORD*>(&buf[8])='eer';
 
  //Получаем адрес функции VirtualFree
  virtual_free_func virtual_free;
  virtual_free =reinterpret_cast<virtual_free_func>(get_proc_address(kernel32_dll, buf));

Этот кусок кода аналогичен коду в шаге 3, где мы загружали user32.dll и получали в ней адрес функции MessageBoxA, так что пояснять не буду. Далее следует перенести в локальную область видимости необходимые переменные, которые для нас запас упаковщик:

//Относительный виртуальный адрес директории импорта
  DWORD original_import_directory_rva;//Виртуальный размер директории импорта
  DWORD original_import_directory_size;//Оригинальная точка входа
  DWORD original_entry_point;//Общий размер всех секций файла
  DWORD total_virtual_size_of_sections;//Количество секций в оригинальном файле
  BYTE number_of_sections;
 
  //Копируем эти значения из структуры packed_file_info,//которую для нас записал упаковщик
  original_import_directory_rva = info->original_import_directory_rva;
  original_import_directory_size = info->original_import_directory_size;
  original_entry_point = info->original_entry_point;
  total_virtual_size_of_sections = info->total_virtual_size_of_sections;
  number_of_sections = info->number_of_sections;

Мы это сделали потому, что скоро структура packed_file_info, находящаяся в самом начале первой секции упакованного файла, будет затерта реальными распакованными данными. Теперь выделим память и распакуем в нее упакованный блок данных:

//Указатель на память, в которую//мы запишем распакованные данные
  LPVOID unpacked_mem;//Выделяем память
  unpacked_mem = virtual_alloc(0,
    info->size_of_unpacked_data,
    MEM_COMMIT,
    PAGE_READWRITE);
 
  //Выходной размер распакованных данных//(эта переменная, в принципе, не нужна)
  lzo_uint out_len;
  out_len =0;
 
  //Производим распаковку алгоритмом LZO
  lzo1z_decompress(reinterpret_cast<constunsignedchar*>(reinterpret_cast<DWORD>(info)+sizeof(packed_file_info)),
    info->size_of_packed_data,
    reinterpret_cast<unsignedchar*>(unpacked_mem),
    &out_len,
    0);

Инициализировать алгоритм LZO перед распаковкой не нужно, для распаковки достаточно вызвать единственную функцию, что мы и сделали. Далее вычислим виртуальный адрес заголовка первой секции.

//Указатель на DOS-заголовок файлаconst IMAGE_DOS_HEADER* dos_header;//Указатель на файловый заголовок
  IMAGE_FILE_HEADER* file_header;//Виртуальный адрес начала заголовков секций
  DWORD offset_to_section_headers;//Просчитываем этот адрес
  dos_header =reinterpret_cast<const IMAGE_DOS_HEADER*>(original_image_base);
  file_header =reinterpret_cast<IMAGE_FILE_HEADER*>(original_image_base + dos_header->e_lfanew +sizeof(DWORD));//Вот по такой формуле
  offset_to_section_headers = original_image_base + dos_header->e_lfanew + file_header->SizeOfOptionalHeader
    +sizeof(IMAGE_FILE_HEADER)+sizeof(DWORD)/* Signature */;

Теперь мы имеем виртуальный адрес заголовков секций. Нам их необходимо перезаписать, чтобы в памяти они выглядели так, как выглядят в оригинальном файле. Перед тем, как мы будем это делать, необходимо обработать еще кое-какие мелочи:

//Обнулим всю память первой секции//эта область соответствует области памяти, которую//в оригинальном файле занимают все секцииmemset(reinterpret_cast<void*>(original_image_base + rva_of_first_section),
    0,
    total_virtual_size_of_sections - rva_of_first_section);
 
  //Изменим атрибуты блока памяти, в котором//расположены заголовки PE-файла и секций//Нам необходим доступ на запись
  DWORD old_protect;
  virtual_protect(reinterpret_cast<LPVOID>(offset_to_section_headers),
    number_of_sections *sizeof(IMAGE_SECTION_HEADER),
    PAGE_READWRITE, &old_protect);
 
  //Теперь изменим количество секций//в заголовке PE-файла на оригинальное
  file_header->NumberOfSections = number_of_sections;

Приступим к восстановлению заголовков секций:

//Виртуальный адрес структуры заголовка секции
  DWORD current_section_structure_pos;
  current_section_structure_pos = offset_to_section_headers;//Перечислим все секцииfor(int i =0; i != number_of_sections;++i){//Создаем структуру заголовка секции
    IMAGE_SECTION_HEADER section_header;//Обнуляем структуруmemset(&section_header, 0, sizeof(section_header));//Заполняем важные поля://Характеристики
    section_header.Characteristics=(reinterpret_cast<packed_section*>(unpacked_mem)+ i)->characteristics;//Смещение файловых данных
    section_header.PointerToRawData=(reinterpret_cast<packed_section*>(unpacked_mem)+ i)->pointer_to_raw_data;//Размер файловых данных
    section_header.SizeOfRawData=(reinterpret_cast<packed_section*>(unpacked_mem)+ i)->size_of_raw_data;//Относительный виртуальный адрес секции
    section_header.VirtualAddress=(reinterpret_cast<packed_section*>(unpacked_mem)+ i)->virtual_address;//Виртуальный размер секции
    section_header.Misc.VirtualSize=(reinterpret_cast<packed_section*>(unpacked_mem)+ i)->virtual_size;//Копируем оригинальное имя секцииmemcpy(section_header.Name, (reinterpret_cast<packed_section*>(unpacked_mem)+ i)->name, sizeof(section_header.Name));
 
    //Копируем заполненный заголовок//в память, где находятся заголовки секцийmemcpy(reinterpret_cast<void*>(current_section_structure_pos), &section_header, sizeof(section_header));
 
    //Перемещаем указатель на следующий заголовок секции
    current_section_structure_pos +=sizeof(section_header);}

Заголовки секций восстановили, теперь восстановим их данные:

//Указатель на сырые данные секции//Необходим для разлепления сжатых данных секций//и распихивания их по нужным местам
  DWORD current_raw_data_ptr;
  current_raw_data_ptr =0;//Восстановим указатель на заголовки секций
  current_section_structure_pos = offset_to_section_headers;//Снова перечисляем все секцииfor(int i =0; i != number_of_sections;++i){//Заголовок секции, который мы только что сами записалиconst IMAGE_SECTION_HEADER* section_header =reinterpret_cast<const IMAGE_SECTION_HEADER*>(current_section_structure_pos);
 
    //Копируем данные секции в то место памяти,//где они должны располагатьсяmemcpy(reinterpret_cast<void*>(original_image_base + section_header->VirtualAddress),
      reinterpret_cast<char*>(unpacked_mem)+ number_of_sections *sizeof(packed_section)+ current_raw_data_ptr,
      section_header->SizeOfRawData);
 
    //Перемещаем указатель на данные секции//в распакованном блоке данных
    current_raw_data_ptr += section_header->SizeOfRawData;
 
    //Переходим к следующему заголовку секции
    current_section_structure_pos +=sizeof(IMAGE_SECTION_HEADER);}
 
  //Освобождаем память с распакованными данными,//она нам больше не нужна
  virtual_free(unpacked_mem, 0, MEM_RELEASE);

И, почти все готово. Чтобы упакованный файл запустился, остается лишь пофиксить его таблицу импорта, снова выступив в роли PE-загрузчика. Для начала пофиксим виртуальный адрес и размер таблицы импорта в PE-заголовке:

//Вычислим относительный виртуальный адрес//начала таблицы директорий
  DWORD offset_to_directories;
  offset_to_directories = original_image_base + dos_header->e_lfanew
    +sizeof(IMAGE_NT_HEADERS32)-sizeof(IMAGE_DATA_DIRECTORY)* IMAGE_NUMBEROF_DIRECTORY_ENTRIES;
 
  //Указатель на директорию импорта
  IMAGE_DATA_DIRECTORY* import_dir =reinterpret_cast<IMAGE_DATA_DIRECTORY*>(offset_to_directories +sizeof(IMAGE_DATA_DIRECTORY)* IMAGE_DIRECTORY_ENTRY_IMPORT);//Записываем значения размера и виртуального адреса в соответствующие поля
  import_dir->Size = original_import_directory_size;
  import_dir->VirtualAddress = original_import_directory_rva;

Заполняем таблицу импорта:

//Если у файла имеются импортыif(original_import_directory_rva){//Виртуальный адрес первого дескриптора
    IMAGE_IMPORT_DESCRIPTOR* descr;
    descr =reinterpret_cast<IMAGE_IMPORT_DESCRIPTOR*>(original_import_directory_rva + original_image_base);
 
    //Перечисляем все дескрипторы//Последний - нулевойwhile(descr->Name){//Загружаем необходимую DLL
      HMODULE dll;
      dll = load_library_a(reinterpret_cast<char*>(descr->Name + original_image_base));//Указатели на таблицу адресов и lookup-таблицу
      DWORD* lookup, *address;//Учтем, что lookup-таблицы может и не быть,//как я говорил в предыдущем шаге
      lookup =reinterpret_cast<DWORD*>(original_image_base +(descr->OriginalFirstThunk ? descr->OriginalFirstThunk : descr->FirstThunk));
      address =reinterpret_cast<DWORD*>(descr->FirstThunk + original_image_base);
 
      //Перечисляем все импорты в дескриптореwhile(true){//До первого нулевого элемента в лукап-таблице
        DWORD lookup_value =*lookup;if(!lookup_value)break;
 
        //Проверим, импортируется ли функция по ординалуif(IMAGE_SNAP_BY_ORDINAL32(lookup_value))*address =static_cast<DWORD>(get_proc_address(dll, reinterpret_cast<constchar*>(lookup_value & ~IMAGE_ORDINAL_FLAG32)));else*address =static_cast<DWORD>(get_proc_address(dll, reinterpret_cast<constchar*>(lookup_value + original_image_base +sizeof(WORD))));
 
        //Переходим к следующему элементу++lookup;++address;}
 
      //Переходим к следующему дескриптору++descr;}}

Вот и все, мы, как PE-загрузчик, заполнили PE-файлу таблицу импорта. Осталась пара мелочей:

//Вернем атрибуты памяти заголовков, как было изначально
  virtual_protect(reinterpret_cast<LPVOID>(offset_to_section_headers), number_of_sections *sizeof(IMAGE_SECTION_HEADER), old_protect, &old_protect);
 
  //Эпилог вручную
  _asm
  {//Переходим на оригинальную точку входа
    mov eax, original_entry_point;
    add eax, original_image_base;
    leave;//Вот так
    jmp eax;}

Теперь вы поняли, зачем нам нужны были собственные пролог и эпилог функции на ассемблере. Вместо инструкции ret, которая раньше располагалась в самом конце кода распаковщика, мы поставили инструкцию jmp eax, осуществляющую переход на код оригинального файла.

Итак, распаковщик теперь сможет запустить простейший PE-файл, имеющий только таблицу импорта. Любой файл с ресурсами, TLS, экспортами работать не будет, и этим мы займемся в следующих шагах. Но мы уже можем запаковать сами себя и запустить запакованный вариант!

Как видно, мы запаковали сами себя, получив бинарник packed_simple_pe_packer.exe, и он работает!

Полный солюшен со всеми проектами для данного шага: Own PE Packer Step 4

Также рекомендую почитать

 Обсудить на форуме


Источник: http://feedproxy.google.com/~r/kaimi/dev/~3/hJHKtytjSyU/

Пишем упаковщик по шагам. Шаг четвертый. Запускаем. | | 2012-09-17 20:31:18 | | Блоги и всяко-разно | | Предыдущий шаг: здесь.Появилась новая версия библиотеки для работы с PE-файлами (0.1.4). Перекачайте и пересоберите ее.Итак, из прошлых шагов мы имеем работающий упаковщик и базовый распаковщик, | РэдЛайн, создание сайта, заказать сайт, разработка сайтов, реклама в Интернете, продвижение, маркетинговые исследования, дизайн студия, веб дизайн, раскрутка сайта, создать сайт компании, сделать сайт, создание сайтов, изготовление сайта, обслуживание сайтов, изготовление сайтов, заказать интернет сайт, создать сайт, изготовить сайт, разработка сайта, web студия, создание веб сайта, поддержка сайта, сайт на заказ, сопровождение сайта, дизайн сайта, сайт под ключ, заказ сайта, реклама сайта, хостинг, регистрация доменов, хабаровск, краснодар, москва, комсомольск |
 
Дайджест новых статей по интернет-маркетингу на ваш email
Подписаться

Продающие сайты "под ключ"!

Наши сайты зарабытывают вам деньги. Landing-page. Эффективные продающие сайты точно в срок и под ключ! Всего от 14700 рублей
Подробнее...

Интернет-магазины и каталоги "под ключ"!

Эффективные и удобные инструменты торговли (электронной торговли) "под ключ". Продают, даже когда вы спите! Всего от 33800 рублей
Подробнее...

Комплексный интернет-маркетинг и продвижение сайтов

Максимальную эффективность дает не какой-то конкретный метод, а их комбинация. Комбинация таких методов и называется комплексным интернет-маркетингом. Всего от 8000 рублей в месяц
Подробнее...

Реклама в Yandex и Google

Контекстная реклама нацелена лишь на тех пользователей, которые непосредственно заинтересованы в рекламе Ваших услуг или товаров. Всего от 8000 рублей в месяц
Подробнее...

Social media marketing (SMM) — продвижение в социальных медиа

Реклама в Однокласcниках и на Mail.ru Создание, ведение и раскрутка групп и реклама ВКонтакте и Facebook. Всего от 8000 рублей в месяц
Подробнее...

Приглашаем к сотрудничеству рекламные агентства и веб-студии!

Внимание Акция! Приглашаем к сотрудничеству рекламные агентства и различные веб-студии России! Индивидуальные и взаимовыгодные условия сотрудничества.
Подробнее...

Ускоренная разработка любого сайта от 5 дней!

Внимание Акция! Ускоренная разработка любого сайта! Ваш сайт будет готов за 5-10 дней. Вы можете заказать разработку любого сайта "под ключ" за 5-10 рабочих дней, с доплатой всего 30% от его стоимости!
Подробнее...

Ждем новых друзей!

Внимание Акция! Ждем новых друзей! Скидка 10% на услуги по созданию и(или) обслуживанию вашего сайта при переходе к нам от другого разработчика.
Подробнее...

Приведи друга и получи скидку!

Внимание Акция! Приведи друга и получи скидку! Скидка 10% на услуги по созданию и(или) обслуживанию вашего сайта, если клиент заказавший наши услуги, пришел по Вашей рекомендации.
Подробнее...

1 2 3 4 5 6 7 8 9

Новые статьи и публикации



Мы создаем сайты, которые работают! Профессионально обслуживаем и продвигаем их , а также по всей России и ближнему зарубежью с 2006 года!

Качественное и объемное представление своего бизнеса в Сети требуется любой растущей коммерческой структуре, стремящейся увеличить продажи, именно по этой причине среди наших клиентов как крупные так и небольшие компании во многих городах России и ближнего зарубежья.
Как мы работаем

Заявка
Позвоните или оставьте заявку на сайте.


Консультация
Обсуждаем что именно Вам нужно и помогаем определить как это лучше сделать!


Договор
Заключаем договор на оказание услуг, в котором прописаны условия и обязанности обеих сторон.


Выполнение работ
Непосредственно оказание требующихся услуг и работ по вашему заданию.


Поддержка
Сдача выполненых работ, последующие корректировки и поддержка при необходимости.

Остались еще вопросы? Просто позвоните и задайте их специалистам
с 2:30 до 11:30 по Мск, звонок бесплатный
Или напишите нам в WhatsApp
с 9:30 до 18:30 по Хабаровску
Или напишите нам в WhatsApp
Веб-студия и агентство комплексного интернет-маркетинга «РЭДЛАЙН» © 2006 - 2024

Профессиональная Веб-разработка. Создание сайтов и магазинов "под ключ" , а также по всей России и зарубежью. Продвижение и реклама. Веб-дизайн. Приложения. Сопровождение. Модернизация. Интеграции. Консалтинг. Продвижение и реклама. Комплексный Интернет-маркетинг.

Оставьте заявку / Задайте вопрос

Нажимая на кнопку ОТПРАВИТЬ, я даю согласие на обработку персональных данных
×

Заказать услугу

Нажимая на кнопку ОТПРАВИТЬ, я даю согласие на обработку персональных данных
×

Обратный звонок

Нажимая на кнопку ОТПРАВИТЬ, я даю согласие на обработку персональных данных
×

Подписка на дайджест новостей

Нажимая на кнопку ОТПРАВИТЬ, я даю согласие на обработку персональных данных
×

Заказать услуги со скидкой \ Бесплатная консультация







КАКИЕ УСЛУГИ ВАС ИНТЕРЕСУЮТ?

КАКИЕ ДОПОЛНИТЕЛЬНЫЕ УСЛУГИ ПОТРЕБУЮТСЯ?

Нажимая на кнопку ОТПРАВИТЬ, я даю согласие на обработку персональных данных
×

Высококачественные сайты по доступным ценамМы создаем практически любые сайты от продающих страниц до сложных, высоконагруженных и нестандартных веб приложений! Наши сайты это надежные маркетинговые инструменты для успеха Вашего бизнеса и увеличения вашей прибыли! Мы делаем красивые и максимально эффектные сайты по доступным ценам уже много лет!

Что нужно сделать, чтобы заказать создание сайта у нас?

Ну для начала вам нужно представлять (хотя бы в общих чертах), что вы хотите получить от сайта и возможно каким вы хотите его видеть. А дальше все просто. Позвоните нам или оставьте заявку нашим менеджерам, чтобы они связались с Вами, проконсультировали и помогли определиться с подходящим именно Вам сайтом по цене, сроку, дизайну или функционалу. Если вы все ещё не уверены, какой сайт вам нужен, просто обратитесь к нам! Мы вместе проанализируем вашу ситуацию и определим максимально эффективный для вас вариант.

Быстрый заказ \ Консультация

Для всех тарифных планов на создание и размещение сайтов включено:

Комплексная раскрутка сайтов и продвижение сайта Комплексный подход это не просто продвижение сайта, это целый комплекс мероприятий, который определяется целями и задачами поставленными перед сайтом и организацией, которая за этим стоит. Время однобоких методов в продвижении сайтов уже прошло, конкуренция слишком высока, чтобы была возможность расслабиться и получать \ удерживать клиентов из Интернета, просто сделав сайт и не занимаясь им...

Комплексная раскрутка работает в рамках стратегии развития вашего бизнеса в сети и направлена

Быстрый заказ \ Консультация

ЭФФЕКТИВНОЕ СОПРОВОЖДЕНИЕ (ПОДДЕРЖКА, ОБСЛУЖИВАНИЕ) САЙТОВ

Полный комплекс услуг по сопровождению сайтаМы оказываем полный комплекс услуг по сопровождению сайта: информационному и техническому обслуживанию и развитию Интернет сайтов.

Передав свой сайт для поддержки в руки наших специалистов, Вы избавитесь от проблем, связанных с обновлением информации и контролем за работой ресурса.

Наша компания осуществляет техническую и информационную поддержку уже имеющихся сайтов. В понятие «поддержка сайтов» также входят услуги администрирования сайтов, обновления сайтов и их модернизация.

Быстрый заказ \ Консультация

Редизайн сайта и Адаптивный веб дизайн

Современный, технологичный, кроссбраузерный ... Профессиональный дизайн сайтов и веб-приложений

Редизайн сайта — создание нового дизайна сайта с целью улучшения внешнего вида, функциональности и удобства использования. Редизайн сайта – это способ преобразовать проект к извлечению из него максимальной отдачи и средств. В современном мире задачами редизайна является поднятие существующего сайта на новый уровень для внедрения новых технологий, при этом сохраняя многолетний сформировавшийся опыт и успешные решения компаний.

Адаптивный дизайн сайтов и веб-приложений

Все больше людей пользуются мобильными устройствами (телефонами, планшетами и прочими) для посещения Интернета, это не для кого уже не новость. Количество таких людей в процентном отношении будет только больше с каждым годом, потому что это удобно и по многим другим причинам.

На сегодняшний день адаптивный дизайн является стандартным подходом при разработке новых сайтов (или веб-приложений) и в идеале ваш сайт должен смотреться и функционировать так, как вы задумывали, на всём разнообразии устройств.

Быстрый заказ \ Консультация

Контекстная реклама в Яндекс и GoogleКонтекстная реклама - это эффективный инструмент в интернет маркетинге, целью которого является увеличение продаж. Главный плюс контекстной рекламы заключается в том, что она работает избирательно.

Реклама в поисковых системах Яндекс и Google. Профессиональная настройка рекламы и отслеживание эффективности!

Рекламные объявления показываются именно тем пользователям, которые ищут информацию о Ваших товарах или услугах, поэтому такая реклама не является навязчивой и раздражающей в отличие от других видов рекламы, с которыми мы сталкиваемся на телевидении или радио. Контекстная реклама нацелена лишь на тех пользователей, которые непосредственно заинтересованы в рекламе Ваших услуг или товаров.

Быстрый заказ \ Консультация

Скидка

1500 руб.
Заинтересовались услугами создания, обслуживания или продвижения вашей компании в Интернете?!
Получите 1500 руб.
за он-лайн заявку
Предложение ограничено.

После получения заявки с Вами свяжутся наши специалисты и уточнят все детали по интересующей вас услуге.
«Нажимая на кнопку "Получить скидку", я даю согласие на обработку персональных данных»
×
Получите 1500 рублей!
×
×