Análisis Packer 01 - Parte V
Recordando datos
Voy a recordar todos los datos que tenemos:
- OEP (antes de emular los stolen bytes y en el packer): 1B903DE
- -------------------------------------------------------------------------------
- INICIO IAT: 0076D258
- FIN IAT:0076DDE0
- TAMAÑO IAT: B88 bytes
- DIRECCIÓN VIRTUAL RELATIVA (RVA) del inicio de la IAT: 0036D258
- --------------------------------------------------------------------------------------------------
- INICIO INIT TABLE: 0074BB20
- FIN INIT TABLE: 0074C764
- OEP ORIGINAL: 0074C768
- ---------------------------------------
- Tenemos una tabla con todas las calls intermodular.
Preparando el el dumpeado
Iniciamos todo. Usando el script de la parte II para reparar la IAT, vamos a ejecutarla para reparar la IAT y le vamos a decir que nos pare en el OEP en 1B903DE. Ejecuto el script y se detiene en el OEP:
Compruebo la IAT:
0076D250 00000000
0076D254 00000000
0076D258 7C92135A ntdll.RtlDeleteCriticalSection
0076D25C 7C9110E0 ntdll.RtlLeaveCriticalSection
0076D260 7C911000 ntdll.RtlEnterCriticalSection
0076D264 7C809F81 kernel32.InitializeCriticalSection
0076D268 7C809B74 kernel32.VirtualFree
0076D26C 7C809AE1 kernel32.VirtualAlloc
0076D270 7C8099BF kernel32.LocalFree
0076D274 7C809A1D kernel32.LocalAlloc
0076D278 7C81126A kernel32.GetVersion
0076D27C 7C8097B8 kernel32.GetCurrentThreadId
0076D280 7C80980A kernel32.InterlockedDecrement
0076D284 7C8097F6 kernel32.InterlockedIncrement
0076D288 7C80BA61 kernel32.VirtualQuery
0076D28C 7C80A164 kernel32.WideCharToMultiByte
0076D290 7C8360F5 kernel32.SetCurrentDirectoryA
0076D294 7C809C88 kernel32.MultiByteToWideChar
0076D298 7C80BE46 kernel32.lstrlenA
0076D29C 7C8101A1 kernel32.lstrcpynA
0076D2A0 7C801D53 kernel32.LoadLibraryExA
0076D2A4 7C80A4A5 kernel32.GetThreadLocale
0076D2A8 7C801EF2 kernel32.GetStartupInfoA
0076D2AC 00BA9B04 protegid.00BA9B04 <= Sin reparar. Recuerda que habrá 3 sin resolver
0076D2B0 7C80B731 kernel32.GetModuleHandleA
...
0076DDBC 00000000
0076DDC0 00C8BB90 sicmplr.Compiler_DataLink3000
0076DDC4 00C8BBF4 sicmplr.CompileRC
0076DDC8 00000000
0076DDCC 7E3A99CB user32.NotifyWinEvent
0076DDD0 00000000
0076DDD4 77EFD7AE GDI32.GetRandomRgn
0076DDD8 00000000
0076DDDC 7C812B6E kernel32.GetVersionExA
0076DDE0 00000000
Debemos reparar las 3 entradas que quedan sin resolver, recuerda la parte sobre la IAT, así:
0076D2A8 7C801EF2 kernel32.GetStartupInfoA
0076D2AC 7C80AE30 kernel32.GetProcAddress
0076D2B0 7C80B731 kernel32.GetModuleHandleA
...
0076D2F8 7C801812 kernel32.ReadFile
0076D2FC 7C812A99 kernel32.RaiseException
0076D300 7C812FC9 kernel32.GetStdHandle
...
0076D4AC 7C82147D kernel32.GetProfileStringA
0076D4B0 7C80AE30 kernel32.GetProcAddress
0076D4B4 7C832B6E kernel32.GetPrivateProfileStringA
Anexando la INIT TABLE
Vamos a reparar la INIT TABLE que lo haremos de forma rápida y sencilla. Yo la guardé si recuerdas en un archivo de texto, así que lo abro, lo copio todo, y me voy en la ventana de dump de OllyDBG al inicio de la INIT TABLE: 0074BB20, la selecciono entera y botón derecho ratón -> binary -> binary paste. Ya se ha pegado correctamente entera:
0074BB20 00000188
0074BB24 0074BB28 protegid.0074BB28
0074BB28 0040800C protegid.0040800C
0074BB2C 00407FDC protegid.00407FDC
0074BB30 00407E00 protegid.00407E00
...
0074C750 0070A704 protegid.0070A704
0074C754 0070A6D4 protegid.0070A6D4
0074C758 00729F20 protegid.00729F20
0074C75C 00729D58 protegid.00729D58
0074C760 00000000
0074C764 0074BAA4 protegid.0074BAA4
Reparando las calls intermodulars
Como recordarás, todas las calls intermodulars malas se encuentran en una tabla que hicimos. Ahora sencillamente puedes crear un injerto o puedes crear un script para poder repararlas. Yo me decido por un injerto ya que el script tiene muchas limitaciones a la hora de crear algo en ensamblador. Lo primero que haré es pegar la tabla en la dirección 680000 (por ningún motivo especial) y después de repararla la dejaré como estaba (undo selection). El código irá un poco más abajo, en 680500.
¿Qué tiene que hacer el script?
Pues es muy sencillo. Voy a tomar la primera dirección de la tabla de calls malas:
00680000 00401314 protegid.00401314
00680004 7C810EE1 kernel32.GetFileType
La dirección donde está la call mala es: 00401314 así que voy ahí:
0040130A . 8BC0 mov eax,eax
0040130C $- FF25 0CD37600 jmp near dword ptr ds:[76D30C] ; kernel32.CreateFileA
00401312 8BC0 mov eax,eax
00401314 $ E8 E7EC7A01 call 01BB0000
00401319 8B db 8B
0040131A 8BC0 mov eax,eax
He dejado la API de arriba que esa ya está bien. Como puedes observar lo que tiene que hacer el script es transformar la call 01BB0000 en su correspondiente dirección basándose en la IAT. Me voy a la IAT a buscar dónde está GetFileType:
0076D308 7C810EE1 kernel32.GetFileType
Por lo tanto, ya tenemos todos los datos y podemos transformarlo así:
0040130A . 8BC0 mov eax,eax
0040130C $- FF25 0CD37600 jmp near dword ptr ds:[76D30C] ; kernel32.CreateFileA
00401312 8BC0 mov eax,eax
00401314 - FF25 08D37600 jmp near dword ptr ds:[76D308] ; kernel32.GetFileType
0040131A 8BC0 mov eax,eax
Sencillo ¿no?. Voy a crear el injerto reparador. Lo voy a poner debajo de esta tabla en 680500 por ejemplo. Para guardar datos uso la pila para no modificar nada en memoria y que luego no se pueda revertir. Para hacer el injerto en OllyDBG yo uso el plugin Multimate Assembler, realmente muy muy muy útil y que te ahorra muchísimo trabajo. El injerto es el siguiente:
<00680500>
pushad
push 680000 ; Direccion inicio Tabla de calls
@bucle:
mov ecx, 0B88 ; Size IAT
mov edi, 0076D258 ; Direccion inicio IAT
mov ebx, dword [esp]
mov ebx, dword [ebx] ; Direccion call
add dword [esp], 4
mov eax, dword [esp]
mov eax, dword [eax] ; Direccion API
repne scas dword [edi]
jnz short @no_encontrado
@encontrado:
sub edi, 4
mov word [ebx], 025FF
mov dword [ebx+2], edi
add dword [esp], 4
cmp dword [esp], 680450
jnz @bucle
nop ; Breakpoint FINAL
@no_encontrado:
nop ; Breakpoint API no encontrada
pop eax
popad
Pongo el eip al comienzo del injerto, pongo los dos breakpoints que indico y ejecuto el script. No da tiempo ni de pulsar el ratón que ya ha terminado. Observa que bien ha quedado:
00680000 00401314 jmp to kernel32.GetFileType
00680004 7C810EE1 kernel32.GetFileType
00680008 0040131C jmp to kernel32.GetFileSize
0068000C 7C810B07 kernel32.GetFileSize
00680010 00401324 jmp to kernel32.GetStdHandle
...
00680440 00442F88 jmp to comdlg32.ChooseFontA
00680444 7637C1C1 comdlg32.ChooseFontA
00680448 00442F90 jmp to comdlg32.PrintDlgA
0068044C 763846FD comdlg32.PrintDlgA
Antes de seguir te recuerdo que tenemos que dejar todo intacto, por lo tanto, todo lo que hemos usado en la dirección 680000 hay que restaurarlo: undo selection. Importante.
Dumpeando
¡Por fin! después de tanto trabajo ya puedo decir que ya podemos dumpear con OllyDBG:
Quitamos Rebuild Import porque lo vamos a hacer con Import REconstructor y si te fijas he cambiado el Entry Point... Tienes que poner el valor RVA, no la Virtual Address, ¿por qué he cambiado el Entry Point?. Porque es el OEP original y porque voy a restaurar los stolen bytes. Lo guardo como "dumpe.exe".
Reparando la Tabla de Importaciones
Voy a crear una nueva IID, para ello aún con OllyDBG parado en el OEP, ejecuto Import REconstructor y selecciono el proceso: "protegido.exe". Y pongo los datos correctamente que en el tutorial sobre la IAT ya expliqué y están en el inicio de este artículo. Los pongo porque Import REconstructor no atina. Cambio el OEP a 0034C768 y pulso en Get Imports:
Como ya resolvimos las 3 entradas malas pues está toda la IAT perfecta. Pulso en Fix Dump y selecciono "dumpe.exe", se crea "dumpe_.exe". Qué gran trabajo hace Import REconstructor... ¡el tiempo que perderíamos haciéndolo a mano...! Si quiero, para saber dónde ha creado la IID miro el log de Import RE:
*** New section added successfully. RVA:007C5000 SIZE:00004000
Image Import Descriptor size: 244; Total length: 345E
C:\karmanyWeb\Estudio Packer 01\dumpe_.exe saved successfully.
El programa lo dejo parado en el OEP porque en el próximo tutorial veremos cómo descubrir los stolen bytes, partiremos desde el OEP.
Ahora ya tenemos un dumpeado con el OEP original (aunque destrozado), con la INIT TABLE reparada, con la IAT reparada con una nueva sección donde está la IID que nos ha creado Import RE y con las calls intermodulars reparadas. Con todo eso reparado, ya podemos abrir "dumpe.exe" en OllyDBG, examinar todo lo que hemos reparado por si hay algún fallo, y observar que el OEP está destrozado porque faltan los stolen bytes.