Для закріплення розуміння деяких моментів патчингу FASM'у, мені закортіло додати директиву, котра б розраховувала crc32-хеш (практичної цінності нема, бо усе це елементарним чином робиться макросами, але все ж таки).
Відкриваємо TABLES.INC переходимо до мітки data_directives та додамо нашу команду "crc32". Довжина назви - 5 символів, а так як у кожному розділі усі строкові літерали повинні йти у зростаючому порядку за кількістю символів і алфавітом, то назвемо наш новий підрозділ data_directives_5 (якраз після максимальної data_directives_4, яка описує директиву "file")
data_directives_5:
db 'crc32',1
dw data_crc32-instruction_handler
Потім коректуємо саму data_directives наступним чином (що воно значить, приходиться поки тільки догадуватись)
data_directives:
dw data_directives_2-data_directives,(data_directives_3-data_directives_2)/(2+3)
dw data_directives_3-data_directives,(data_directives_4-data_directives_3)/(3+3)
dw data_directives_4-data_directives,(data_directives_5-data_directives_4)/(4+3)
dw data_directives_5-data_directives,(data_directives_end-data_directives_5)/(5+3)
Далі переходимо до PARSER.INC, і шукаємо процедуру get_data_directive. Так як ми додали один підрозділ (data_directives_5) то у цій процедурі правимо
cmp cl, 4
на
cmp cl, 5
Задумка така:
crc32_MessageBoxA crc32 'MessageBoxA'
crc32_MessageBoxA - мітка
crc32 - команда
'MessageBoxA' - текст, хеш-суму котрого ми рахуємо
Відкриваємо ASSEMBLER.INC і в кінець додаєм наступний код:
data_crc32:
lods word[esi]
cmp al, '('
jne invalid_argument
lods dword[esi] ;розмір строки
push eax
call get_crc32 ; в esi - текст, в eax - розмір тексту
stos dword[edi] ; пишем результат
pop eax
add esi, eax ; пропускаємо усю строку
inc esi ; пропускаємо \0
jmp instruction_assembled ; працюємо далі
Відкриваємо SYSTEM.INC та додаємо get_crc32:
get_crc32:
mov edx, esi
mov ecx, eax
xor eax, eax
test ecx, ecx
je @4
not eax
@1: xor al, byte[edx]
inc edx
mov bl, 8h
@2: shr eax, 1h
jae @3
xor eax, 0xEDB88320
@3: dec bl
jne @2
dec ecx
jne @1
not eax
@4:
ret
Якщо поставимо бряк на початок нашої процедури (data_crc32) можемо побачити наступне:
- в esi буфер із виразом
002200F3 28 00 0B 00|00 00 4D 65|73 73 61 67|65 42 6F 78| (....MessageBox
00220103 41 00 00 00|00 00 00 00|00 00 00 00|00 00 00 00| A...............
- в edi буфер-приймач, куди ми запишемо результат, а FASM нам додасть його по місцезнаходженню нашой мітки.
Для перевірки, виконаємо наступний код
use32
mov eax, dword[crc32_MessageBoxA]
mov ecx, dword[crc32_ExitProcess]
crc32_MessageBoxA crc32 'MessageBoxA' ; 0x572D5D8E
crc32_ExitProcess crc32 'ExitProcess' ; 0x251097CC
Усе працює