Hola a todos, estoy haciendo un pequeño virus (sin ánimo de soltarlo, claro, solo como POC) y tras mucho debuggear con el Olly resulta que me lanza una ACCESS_VIOLATION tras llamar a LoadLibraryA en una función que realiza el mismo trabajo que GetProcAddress pero pasándole en su lugar un CRC32, alguien puede ayudarme? Las pruebas las he hecho en un Win 7 x64. Aquí adjunto el código de la función:
@@get_proc:
; [OnEntry]
; edx => crc32
; ebx => hModule
; [OnExit]
; eax => lpfnApi / NULL (OnError)
assume ebx:ptr IMAGE_DOS_HEADER
push edi
push esi
push ebp
mov edi,ebx
add edi,[ebx].e_lfanew
assume edi:ptr IMAGE_NT_HEADERS
mov edi,[edi].OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress
add edi,ebx
assume edi:ptr IMAGE_EXPORT_DIRECTORY
xor ecx,ecx
mov esi,[edi].AddressOfNames
add esi,ebx
mov ebp,[edi].NumberOfNames
@@apiname_loop:
lodsd
add eax,ebx
xchg eax,esi
push eax ; save AddressOfNames
push ecx
call @@strlen
xchg eax,ecx
push edx
call @@crc32
pop edx
pop ecx
pop esi
cmp eax,edx
jnz @@not_api_hash
mov esi,[edi].AddressOfNameOrdinals
add esi,ebx
shl ecx,1h
add esi,ecx
movzx ecx,word ptr [esi]
shl ecx,2h
mov esi,[edi].AddressOfFunctions
add esi,ebx
add esi,ecx
mov eax,dword ptr [esi]
; code here to check whether we are being forwarded (does the RVA fall into the .edata?)
mov ebp,ebx
add ebp,[ebx].e_lfanew
assume ebp:ptr IMAGE_NT_HEADERS
mov ecx,[ebp].OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress ; thanks to Matt Pietrek
cmp eax,ecx
jb @@not_forwarded
add ecx,[ebp].OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].isize
cmp eax,ecx
ja @@not_forwarded
@@get_forwarded:
pop ebp
add eax,ebx
xchg esi,eax
call @@strlen
push ecx
push GMEM_FIXED
call dword ptr [ebp + delta(f_globalalloc)]
xchg eax,edi
push edi ; there could be a bug: if someone makes a fwd api without a dot, the host will crash
@@:
lodsb
stosb
cmp al,'.'
jne @@not_dot
mov eax,'lld'
stosd
jmp @@match_dot
@@not_dot:
loop @B
@@match_dot:
call dword ptr [ebp + delta(f_loadlibrary)] ; I know the program won't be able to free the library (i don't know yet how ms loader does it)
push esi
push eax
call dword ptr [ebp + delta(f_getprocaddress)]
push eax
push edi
call dword ptr [ebp + delta(f_globalfree)]
pop eax
jmp @@fwd_api_found
@@not_forwarded:
add eax,ebx
jmp @@api_found
@@not_api_hash:
inc ecx
cmp ecx,ebp ; I need ecx as a counter
jbe @@apiname_loop
@@not_found:
xor eax,eax
@@api_found:
pop ebp
@@fwd_api_found:
pop esi
pop edi
ret
@@strlen:
; [OnEntry]
; esi => [StringA]
; [OnExit]
; eax => Length
xchg esi,edi
xor eax,eax
xor ecx,ecx
dec ecx
push edi
repnz scasb
pop edi
inc ecx
not ecx
xchg eax,ecx
xchg esi,edi
ret
.const
POLYNOM equ 0edb88320h
.code
@@crc32:
; [OnEntry]
; esi => [Mem]
; ecx => count
; [OnExit]
; eax => crc32
xor edx,edx
dec edx
@@crc_loop:
mov eax,edx
and eax,0ffh
xor al,byte ptr [esi]
push ecx
mov ecx,8h
@@:
test al,1h
jz @@bit_not_set
shr eax,1h
xor eax,POLYNOM
jmp @@bit_continue
@@bit_not_set:
shr eax,1h
@@bit_continue:
loop @B
pop ecx
inc esi
shr edx,8h
xor edx,eax
loop @@crc_loop
xchg eax,edx
not eax
ret
Tras tracear un poco veo que las llamadas van así:
- LoadLibraryA -> LoadLibraryExA -> KernelBase.749B6DEF -> ntdll.RtlAnsiStringToUnicodeString -> ...
(http://www.elenalermadansa.com/UserFiles/Media/crash.jpg)
Les agradezco cualquier ayuda/opinión/orientación sobre el tema
PD: Acabo de comprobar que en XP funciona perfectamente, puede ser por algo relacionado con WOW32? O tal vez es por Win7?
Ah, y perdon por un tema/post tan largo, es que no quiero que falte nada de info
Comprueba que no malformas el stack. Ya que LoadLibrary no debería intentar escribir en ningún lado.
OK, acabo de solucionarlo:
-> Por un lado, debe de haber algun bug/incompatibilidad con el Stealth64 del OllyDbg en Win7, ya que el Olly del XP no tenía plugins y iba, y al desactivarlo también va en Win7
-> Por el otro, había un pequeño bug en otra parte de mi código que no preservaba el antiguo EDI, y entonces FindNextFileA lo usaba después de haber sido liberado (y por eso tampoco iba fuera del Olly) (en XP SEH me salvaba) XD
En fín, muchas gracias de todas formas.
PD: por cierto, si quereis hacer uso del código o teneis alguna pregunta, no dudeis en postear (pa eso estamos,no?) :)