Antichat снова доступен.
Форум Antichat (Античат) возвращается и снова открыт для пользователей.
Здесь обсуждаются безопасность, программирование, технологии и многое другое.
Сообщество снова собирается вместе.
Новый адрес: forum.antichat.xyz
 |
Пишем простейший джойнер файлов |

02.12.2009, 23:53
|
|
Новичок
Регистрация: 02.12.2009
Сообщений: 16
Провел на форуме: 101734
Репутация:
21
|
|
Пишем простейший джойнер файлов
Пишем простейший джойнер файлов. Часть 1.
Код:
Эта статья разбита на две части: 1. написание лоадера,
2. написание билдера.
Хочу сказать, что статья написана для _новичков_.
Люди знающие здесь ничего нового не узнают.
I. ИНСТРУМЕНТЫ.
- FASM (www.flatassembler.net);
- немного терпения.
II. ЛОАДЕР. Что это, принцип работы нашего лоадера.
В нашем случае, под лоадером понимается .exe файл, состоящий из
распаковщика и данных, которые дописываются в конец файла. При
запуске, распаковщик считывает эти данные и делает необходимые
действия (сохранить на диск, запустить и т.д.).
Для того, чтобы распаковщик знал, что делать с данными, они должны
быть как-то структурированы. Мы пишем простейший джойнер, поэтому с
заголовком мудрить не будем. Всё сделаем по минимуму.
Что нам надо? Имя файла, длина имени файла, размер данных, и, допустим,
параметры командной строки и её длина. Схематично, это можно изобразить так:
.-------------------,
¦ код распаковщика ¦
|-------------------|
¦ заголовок 1 ¦
¦ данные 1 ¦
|-------------------|
¦ заголовок 2 ¦
¦ данные 2 ¦
|-------------------|
¦ заголовок N ¦
¦ данные N ¦
`-------------------'
Схема 1. Простейший лоадер.
Но как распаковщик узнает, где он заканчивается, а где начинаются данные?
Очень просто. В самом распаковщике мы создадим константу и назовем ее,
например, ldr_size. Ей присвоим значение, равное размеру распаковщика.
Откуда мы узнаем размер распаковщика? Самый простой способ:
1. Собираем наш лоадер;
2. смотрим его размер;
3. присваиваем ldr_size размер;
4. пересобираем.
Таким образом, принцип работы нашего лоадера следующий:
а) открываем себя для чтения;
б) смещаемся на ldr_size байт;
в) обрабатываем заголовок;
г) обрабатываем данные (создаём (скрытый) и запускаем файл);
д) считываем следующий заголовок;
е) если его нет, то выходим, иначе пункт в).
III. НАПИСАНИЕ ЛОАДЕРА.
Ну что же, с теоретической частью закончили. Можно приступить к практике.
Писать сам лоадер мы будем на ассемблере, используя fasm. Ниже приведён
полный исходный код. Я его немного прокомментировал, чтобы новичку было
легче разобраться.
Как вы увидите, ничего сложного здесь нет. Читайте комментарии, смотрите
документацию, погоняйте в отладчике. Я не исключаю, что где-то мог допустить
ошибку. Значит вам её и исправлять.
Код:
;-------------------------------------------------------------------------------
format PE GUI 4.0
;-------------------------------------------------------------------------------
include 'win32ax.inc'
;-------------------------------------------------------------------------------
section '.data' data readable writeable
lnFileName dw 0 ; word для длины имени файла и
lnCmdLine dw 0 ; командной строки хватит вполне.
lnFileSize dd 0 ; длина файла (данных)
szFileName rb 100h ; резервируем 100h байт для имени файла и
szCmdLine rb 100h ; командной строки.
szModule rb 100h ; путь нашего модуля
ldr_size dd 0 ; здесь будет размер лоадера, после ассемблирования
hModule dd 0 ; Хендл файла-лоадера
hFiles dd 0 ; Хендл созданных файлов (данных)
hAllocMem dd 0 ; Для резервирования памяти (для файлов)
nBytesRead dd 0 ; Количество прочитанных байт
;-------------------------------------------------------------------------------
section '.code' code readable writeable executable
entry $
; Получим путь к нашему файлу
invoke GetModuleFileName, NULL, szModule, 100h
; Открываем наш файл для чтения/записи
invoke CreateFile, szModule, GENERIC_READ, \
FILE_SHARE_READ or FILE_SHARE_WRITE, \
NULL, \
OPEN_EXISTING, \
0, 0
cmp eax, -1 ; если не открылся
jz .close ; то выйдем
mov [hModule], eax ; сохраним хендл открытого файла
;----------------------------------------------,
; 2560 я получил после первого ассемблирования |
; Например, упаковав лоадер с помощью upack, |
; я получил размер 1280 байт. Я их впишу сюда, |
; пересоберу и снова запакую. Только тогда |
; распаковщик отработает корректно. |
mov [ldr_size], 2560; |
;----------------------------------------------'
; Установим указатель в файле
; на конец распаковщика (FILE_BEGIN+lde_size)
invoke SetFilePointer, [hModule], [ldr_size], 0, FILE_BEGIN
.loop:
; Прочитаем наш заголовок (8 байт)
invoke ReadFile, [hModule], lnFileName, 8, nBytesRead, 0
test dword [nBytesRead], -1 ; если ничего не прочиталось,
jz .close_1 ; то выйдем (ошибка)
movzx eax, word [lnCmdLine] ; eax = длина параметров
; Прочитаем командную строку из заголовка
invoke ReadFile, [hModule], szCmdLine, eax, nBytesRead, 0
test dword [nBytesRead], -1
jz .close_1
movzx eax, word [lnFileName] ; eax = длина имени файла
or eax, eax ; если 0 (файлов нет),
jz .close_1 ; то выйдем
; иначе прочитаем имя файла
invoke ReadFile, [hModule], szFileName, eax, nBytesRead, 0
test dword [nBytesRead], -1
.close_1: jz .the_end
; и создадим файл с именем szFileName
invoke CreateFile, szFileName, GENERIC_WRITE, FILE_SHARE_READ, 0, \
CREATE_ALWAYS, FILE_ATTRIBUTE_HIDDEN, 0
cmp eax, -1 ; если не создался,
je .loop ; то начнем заново
mov [hFiles], eax ; сохраним хендл файла
; Выделяем память по размеру файла
invoke GlobalAlloc, GMEM_FIXED, [lnFileSize]
or eax, eax
jz .close
mov [hAllocMem], eax
; Прочитаем файл в выделенную память
invoke ReadFile, [hModule], [hAllocMem], [lnFileSize], nBytesRead, 0
test dword [nBytesRead], -1
jz .close
; А теперь из памяти запишем на диск
invoke WriteFile, [hFiles], [hAllocMem], [lnFileSize], nBytesRead, 0
.close:
invoke CloseHandle, [hFiles] ; Закреом хендл файла (данных)
invoke GlobalFree, [hAllocMem] ; Освободим память
; Запустим файл
invoke ShellExecute, 0, 0, szFileName, szCmdLine, 0, SW_SHOW
jmp .loop
.the_end::
invoke CloseHandle, [hModule] ; закроем хендл лоадера
.exit:
invoke ExitProcess, 0 ; выход
;-------------------------------------------------------------------------------
section '.idata' import data readable
library kernel32,'KERNEL32.DLL',\
shell32,'SHELL32.DLL'
include 'api\kernel32.inc'
include 'api\shell32.inc'
;-------------------------------------------------------------------------------
Код:
IV. ПОСЛЕСЛОВИЕ.
В следующей части я покажу, как написать простейший билдер к нашему
лоадеру и получить полноценный склейщик файлов. А пока, в качестве
домашнего задания, попробуйте сделать билдер сами.
Также, файлы легко склеить руками. Нам известен заголовок. Остается его
заполнить. Покажу на простом примере.
Имеется файл fasmw.exe. Необходимо прикрепить его к лоадеру, чтобы тот
запустил его с параметрами "hello.asm".
Итак: - имя файла: fasmw.exe (9 байт + 0 в конце, итого 10 или же 0Ah)
- командная строка: hello.asm (тоже 9 байт + 0 в конце, итого 0Ah).
- размер fasmw.exe: 122 880 байт (0001E000h)
То есть заголовок у нас будет такой:
длина длина размер
имени комм. файла
файла строки fasmw.exe
.-^-. .--^--. .----^----.
0A 00 0A 00 00 E0 01 00 дальше идут параметры и имя файла.
\ / \ / \ /
размер: WORD WORD DOUBLE WORD
Всё! Теперь вы в начало fasm.exe запишем заголовок и смело весь файл
припишем в конец нашему лоадеру.
Просто сравните два файла fasmw.exe до и после добавления заголовка
для нашего лоадера.
файл fasmw.exe ДО обработки:
00000000: 4D 5A 80 00-01 00 00 00-04 00 10 00-FF FF 00 00 MZА **
00000010: 40 01 00 00-00 00 00 00-40 00 00 00-00 00 00 00 @ @
00000020: 00 00 00 00-00 00 00 00-00 00 00 00-00 00 00 00
00000030: 00 00 00 00-00 00 00 00-00 00 00 00-80 00 00 00 А
00000040: 0E 1F BA 0E-00 B4 09 CD-21 B8 01 4C-CD 21 54 68 ║ ┤ ═!╕ L═!Th
00000050: 69 73 20 70-72 6F 67 72-61 6D 20 63-61 6E 6E 6F is program canno
00000060: 74 20 62 65-20 72 75 6E-20 69 6E 20-44 4F 53 20 t be run in DOS
00000070: 6D 6F 64 65-2E 0D 0A 24-00 00 00 00-00 00 00 00 mode. $
00000080: 50 45 00 - - - PE
А теперь файл fasmw.exe ПОСЛЕ обработки:
длина длина длина
имени комм. файла Далее идут командная
файла строки fasmw.exe строка и имя файла
00000000: 0A 00 0A 00 00 E0 01 00 68 65 6C 6C-6F 2E 61 73 а hello.as
00000010: 6D 00 46 41 53 4D 57 2E 45 58 45 00-4D 5A 80 00 m FASMW.EXE MZЂ
^^^^^^^^^^^
отсюда пошёл fasmw.exe
00000020: 01 00 00 00 04 00 10 00 FF FF 00 00-40 01 00 00 яя @
00000030: 00 00 00 00 40 00 00 00 00 00 00 00-00 00 00 00 @
00000040: 00 00 00 00 00 00 00 00 00 00 00 00-00 00 00 00
00000050: 00 00 00 00 00 00 00 00 80 00 00 00-0E 1F BA 0E Ђ є
00000060: 00 B4 09 CD 21 B8 01 4C CD 21 54 68-69 73 20 70 ґ Н!ё LН!This p
00000070: 72 6F 67 72 61 6D 20 63 61 6E 6E 6F-74 20 62 65 rogram cannot be
00000080: 20 72 75 6E 20 69 6E 20 44 4F 53 20-6D 6F 64 65 run in DOS mode
00000090: 2E 0D 0A 24 00 00 00 00 00 00 00 00-50 45 00 . $ PE
Вот мы и написали самый простой лоадер для самого простого джойнера.
Разобрали, как можно им пользоваться, даже без билдера.
Я прошу новичков, что читают эту статью, попробуйте во всем разобраться,
чтоб было понятно всё, до последнего байта.
Не спрашивайте, ищите ответы _сами_.
Тогда и только тогда вы легко сможете сделать джойнер более навороченным,
добавить свой функционал.
becensed
Пишем простейший джойнер файлов. Часть 2.
Код:
Эта статья разбита на две части: 1. написание лоадера,
2. написание билдера.
Хочу сказать, что статья написана для _новичков_.
Люди знающие здесь ничего нового не узнают.
I. ИНСТРУМЕНТЫ.
В данной статье я покажу, как сделать простейший билдер для нашего
простейшего лоадера. Лично я буду компилировать всё в Microsoft Visual
Studio 2008, но каждый из вас может выбрать тот пакет, который ему больше
по душе.
Итак, необходимое:
- Microsoft Visual Studio 2008;
- знание Си, WinApi;
- терпение и чуток мозга :)
II. ЧТО ТАКОЕ БИЛДЕР И КАК ОН РАБОТАЕТ?
Билдер, в нашем случае, это программа, которая на входе получает файлы, а
на выходе - один .ехе-файл, при запуске которого запустятся все файлы, что
были даны билдеру. Да-да, это тот самый обычный GUI интерфейс, с кнопками
типа "Добавить файл", "Склеить файлы" и т.п. :)
Работа билдера простая:
1. Открываем лоадер (см 1-ую часть);
2. Открываем файл из списка;
3. Записываем первому файлу заголовок (8 байт)+параметры и имя;
4. Пишем этот файл в конец лоадера.
5. Если открыли все файлы, то выйдем, иначе пункт 2.
Мы немного модифицируем лоадер из первой части, добавим ему ресурсы
(иконку). Это для того, чтобы ее было проще поменять.
Собственно, больше описывать нечего. Всё находится в исходниках билдера.
Не знаю, что там комментировать. Всё должно быть понятно.
Если нет - используйте MSDN, в 90% случаев найдете ответ именно там!
Немного прокомментирую содержимое архива:
| joiner_1.txt - первая часть статьи
| joiner_2.txt - вторая часть статьи (сейчас ее читаете)
|
+---exe
| builder.exe - файл билдера, уже скомпиленный.
|
\---src
| builder.cpp - исходники билдера
| make.bat - мейкфайл, пользуюсь консолью
|
\---res
hkit.exe - тулза, с помощью которой loader.exe превращается
в массив байт.
loader.asm - исходники лоадера
main.ico - иконка лоадера, суйте туда свою, если хотите
Upack.exe - пакер для лоадера.
III. КОНЕЦ.
Смотрите, изучайте. Проще придумать сложно. Сложнее придумать легко.
В этой статье, в двух ее частях, мы рассмотрели, как написать простой, но
полноценный джойнер любого количества файлов. Если у вас будут вопросы, я
постараюсь на них ответить. Только, пожалуйста, прежде, чем спросить
ПОИЩИТЕ ОТВЕТ САМОСТОЯТЕЛЬНО! :)
becensed
СКАЧАТЬ файлы к статье.
Для особо одаренных скажу сразу: это _простейший_ лоадер, его палит _любой_ антивирус. По данному вопросу критику игнорирую.
Последний раз редактировалось becensed; 03.12.2009 в 00:29..
|
|
|
|
 |
|
Здесь присутствуют: 1 (пользователей: 0 , гостей: 1)
|
|
|
|