2

[原创] 照妖镜 PEDIY.CTF2017P.CTF09.九层妖塔.脱壳篇

tritium 2017-11-11 11:15 681

如何让披了外壳的样例露出真身,让IDA对其真身分析

脱壳准备工作,IDA静态分析半自动完成以下函数集静态变量重命名,

其中得到导入表位置,通过IDAPython自动生成OD Script修复IAT,

最后通过IMportRec重新建立导入表

00444108 Hi_crtmain

004442A2 Hi_start

00444509 Hi_Init_UnhandledExceptionFilter

00444515 Hi_UnhandledExceptionFilter

004447BD Hi_security_cookie_init

00489008 Hi_security_cook_not

0048900C Hi_security_cook

004A9B88 Hi_init0

004AD000 Hi_fp_ADVAPI32_RegOpenKeyExW_4AD000

004AD004 Hi_fp_ADVAPI32_RegDeleteValueW_4AD004

004AD008 Hi_fp_ADVAPI32_RegCreateKeyExW_4AD008

004AD00C Hi_fp_ADVAPI32_RegSetValueExW_4AD00C

004AD010 Hi_fp_ADVAPI32_RegDeleteKeyW_4AD010

004AD014 Hi_fp_ADVAPI32_RegEnumKeyExW_4AD014

004AD018 Hi_fp_ADVAPI32_RegQueryInfoKeyW_4AD018

004AD01C Hi_fp_ADVAPI32_RegCloseKey_4AD01C

004AD024 Hi_fp_COMCTL32_InitCommonControlsEx_4AD024

004AD02C Hi_fp_KERNEL32_VirtualAlloc_4AD02C

004AD030 Hi_fp_KERNEL32_ExitProcess_4AD030

004AD034 Hi_fp_KERNEL32_FreeLibrary_4AD034

004AD038 Hi_fp_KERNEL32_GetProcAddress_4AD038

004AD03C Hi_fp_KERNEL32_lstrcmpiW_4AD03C

004AD040 Hi_fp_KERNEL32_LeaveCriticalSection_4AD040

004AD044 Hi_fp_KERNEL32_RaiseException_4AD044

004AD048 Hi_fp_KERNEL32_EnterCriticalSection_4AD048

004AD04C Hi_fp_KERNEL32_GetLastError_4AD04C

004AD050 Hi_fp_KERNEL32_MultiByteToWideChar_4AD050

004AD054 Hi_fp_KERNEL32_SizeofResource_4AD054

004AD058 Hi_fp_KERNEL32_LoadResource_4AD058

004AD05C Hi_fp_KERNEL32_FindResourceW_4AD05C

004AD060 Hi_fp_KERNEL32_LoadLibraryExW_4AD060

004AD064 Hi_fp_KERNEL32_GetModuleFileNameW_4AD064

004AD068 Hi_fp_KERNEL32_InitializeCriticalSectionAndSpinCount_4AD068

004AD06C Hi_fp_KERNEL32_DeleteCriticalSection_4AD06C

004AD070 Hi_fp_KERNEL32_InterlockedDecrement_4AD070

004AD074 Hi_fp_KERNEL32_InterlockedIncrement_4AD074

004AD078 Hi_fp_KERNEL32_GetCurrentThreadId_4AD078

004AD07C Hi_fp_KERNEL32_DecodePointer_4AD07C

004AD080 Hi_fp_KERNEL32_SetLastError_4AD080

004AD084 Hi_fp_KERNEL32_InitializeCriticalSection_4AD084

004AD088 Hi_fp_KERNEL32_GetCurrentThread_4AD088

004AD08C Hi_fp_KERNEL32_GetThreadContext_4AD08C

004AD090 Hi_fp_KERNEL32_CreateFileW_4AD090

004AD094 Hi_fp_KERNEL32_WideCharToMultiByte_4AD094

004AD098 Hi_fp_KERNEL32_GetUserDefaultLangID_4AD098

004AD09C Hi_fp_KERNEL32_lstrcatA_4AD09C

004AD0A0 Hi_fp_KERNEL32_lstrlenA_4AD0A0

004AD0A4 Hi_fp_KERNEL32_WaitForSingleObject_4AD0A4

004AD0A8 Hi_fp_KERNEL32_CloseHandle_4AD0A8

004AD0AC Hi_fp_KERNEL32_CreateThread_4AD0AC

004AD0B0 Hi_fp_KERNEL32_SetThreadPriority_4AD0B0

004AD0B4 Hi_fp_KERNEL32_HeapAlloc_4AD0B4

004AD0B8 Hi_fp_KERNEL32_HeapCreate_4AD0B8

004AD0BC Hi_fp_KERNEL32_HeapDestroy_4AD0BC

004AD0C0 Hi_fp_KERNEL32_Sleep_4AD0C0

004AD0C4 Hi_fp_KERNEL32_CreateFileA_4AD0C4

004AD0C8 Hi_fp_KERNEL32_ReadFile_4AD0C8

004AD0CC Hi_fp_KERNEL32_SetFilePointer_4AD0CC

004AD0D0 Hi_fp_KERNEL32_FindResourceA_4AD0D0

004AD0D4 Hi_fp_KERNEL32_GetOEMCP_4AD0D4

004AD0D8 Hi_fp_KERNEL32_IsValidCodePage_4AD0D8

004AD0DC Hi_fp_KERNEL32_GetCurrentProcess_4AD0DC

004AD0E0 Hi_fp_KERNEL32_FindNextFileA_4AD0E0

004AD0E4 Hi_fp_KERNEL32_FindFirstFileExW_4AD0E4

004AD0E8 Hi_fp_KERNEL32_FindFirstFileExA_4AD0E8

004AD0EC Hi_fp_KERNEL32_FindClose_4AD0EC

004AD0F0 Hi_fp_KERNEL32_EnumSystemLocalesW_4AD0F0

004AD0F4 Hi_fp_KERNEL32_GetUserDefaultLCID_4AD0F4

004AD0F8 Hi_fp_KERNEL32_IsValidLocale_4AD0F8

004AD0FC Hi_fp_KERNEL32_GetLocaleInfoW_4AD0FC

004AD100 Hi_fp_KERNEL32_LCMapStringW_4AD100

004AD104 Hi_fp_KERNEL32_CompareStringW_4AD104

004AD108 Hi_fp_KERNEL32_GetTimeFormatW_4AD108

004AD10C Hi_fp_KERNEL32_GetDateFormatW_4AD10C

004AD110 Hi_fp_KERNEL32_ReadConsoleW_4AD110

004AD114 Hi_fp_KERNEL32_GetConsoleMode_4AD114

004AD118 Hi_fp_KERNEL32_SetConsoleCtrlHandler_4AD118

004AD11C Hi_fp_KERNEL32_HeapReAlloc_4AD11C

004AD120 Hi_fp_KERNEL32_HeapSize_4AD120

004AD124 Hi_fp_KERNEL32_GetACP_4AD124

004AD128 Hi_fp_KERNEL32_WriteFile_4AD128

004AD12C Hi_fp_KERNEL32_GetStdHandle_4AD12C

004AD130 Hi_fp_KERNEL32_GetModuleFileNameA_4AD130

004AD134 Hi_fp_KERNEL32_GetModuleHandleExW_4AD134

004AD138 Hi_fp_KERNEL32_RtlUnwind_4AD138

004AD13C Hi_fp_KERNEL32_TlsFree_4AD13C

004AD140 Hi_fp_KERNEL32_TlsSetValue_4AD140

004AD144 Hi_fp_KERNEL32_TlsGetValue_4AD144

004AD148 Hi_fp_KERNEL32_TlsAlloc_4AD148

004AD14C Hi_fp_KERNEL32_InterlockedFlushSList_4AD14C

004AD150 Hi_fp_KERNEL32_GetCPInfo_4AD150

004AD154 Hi_fp_KERNEL32_TerminateProcess_4AD154

004AD158 Hi_fp_KERNEL32_GetSystemTimeAsFileTime_4AD158

004AD15C Hi_fp_KERNEL32_GetCurrentProcessId_4AD15C

004AD160 Hi_fp_KERNEL32_QueryPerformanceCounter_4AD160

004AD164 Hi_fp_KERNEL32_GetStartupInfoW_4AD164

004AD168 Hi_fp_KERNEL32_SetUnhandledExceptionFilter_4AD168

004AD16C Hi_fp_KERNEL32_UnhandledExceptionFilter_4AD16C

004AD170 Hi_fp_KERNEL32_GetModuleHandleW_4AD170

004AD174 Hi_fp_KERNEL32_VirtualFree_4AD174

004AD178 Hi_fp_KERNEL32_OutputDebugStringA_4AD178

004AD17C Hi_fp_KERNEL32_SetStdHandle_4AD17C

004AD180 Hi_fp_KERNEL32_GetStringTypeW_4AD180

004AD184 Hi_fp_KERNEL32_SetFilePointerEx_4AD184

004AD188 Hi_fp_KERNEL32_FlushFileBuffers_4AD188

004AD18C Hi_fp_KERNEL32_GetConsoleCP_4AD18C

004AD190 Hi_fp_KERNEL32_SetEndOfFile_4AD190

004AD194 Hi_fp_KERNEL32_GetFileType_4AD194

004AD198 Hi_fp_KERNEL32_SetEnvironmentVariableW_4AD198

004AD19C Hi_fp_KERNEL32_SetEnvironmentVariableA_4AD19C

004AD1A0 Hi_fp_KERNEL32_FreeEnvironmentStringsW_4AD1A0

004AD1A4 Hi_fp_KERNEL32_GetEnvironmentStringsW_4AD1A4

004AD1A8 Hi_fp_KERNEL32_GetCommandLineW_4AD1A8

004AD1AC Hi_fp_KERNEL32_GetCommandLineA_4AD1AC

004AD1B0 Hi_fp_KERNEL32_CreateEventW_4AD1B0

004AD1B4 Hi_fp_KERNEL32_WaitForSingleObjectEx_4AD1B4

004AD1B8 Hi_fp_KERNEL32_ResetEvent_4AD1B8

004AD1BC Hi_fp_KERNEL32_FindNextFileW_4AD1BC

004AD1C0 Hi_fp_KERNEL32_WriteConsoleW_4AD1C0

004AD1C4 Hi_fp_KERNEL32_SetEvent_4AD1C4

004AD1C8 Hi_fp_KERNEL32_LoadLibraryExA_4AD1C8

004AD1CC Hi_fp_KERNEL32_IsDebuggerPresent_4AD1CC

004AD1D0 Hi_fp_KERNEL32_OutputDebugStringW_4AD1D0

004AD1D4 Hi_fp_KERNEL32_EncodePointer_4AD1D4

004AD1D8 Hi_fp_KERNEL32_HeapFree_4AD1D8

004AD1DC Hi_fp_KERNEL32_GetProcessHeap_4AD1DC

004AD1E0 Hi_fp_KERNEL32_InitializeSListHead_4AD1E0

004AD1E4 Hi_fp_KERNEL32_InterlockedPopEntrySList_4AD1E4

004AD1E8 Hi_fp_KERNEL32_InterlockedPushEntrySList_4AD1E8

004AD1EC Hi_fp_KERNEL32_FlushInstructionCache_4AD1EC

004AD1F0 Hi_fp_KERNEL32_IsProcessorFeaturePresent_4AD1F0

004AD1F8 Hi_fp_OLEAUT32_SysFreeString_4AD1F8

004AD1FC Hi_fp_OLEAUT32_VarUI4FromStr_4AD1FC

004AD204 Hi_fp_PSAPI_GetModuleInformation_4AD204

004AD20C Hi_fp_USER32_MessageBoxW_4AD20C

004AD210 Hi_fp_USER32_MessageBoxTimeoutW_4AD210

004AD214 Hi_fp_USER32_KillTimer_4AD214

004AD218 Hi_fp_USER32_SetFocus_4AD218

004AD21C Hi_fp_USER32_GetWindow_4AD21C

004AD220 Hi_fp_USER32_GetWindowLongW_4AD220

004AD224 Hi_fp_USER32_GetMonitorInfoW_4AD224

004AD228 Hi_fp_USER32_GetWindowRect_4AD228

004AD22C Hi_fp_USER32_GetParent_4AD22C

004AD230 Hi_fp_USER32_GetClientRect_4AD230

004AD234 Hi_fp_USER32_MapWindowPoints_4AD234

004AD238 Hi_fp_USER32_SetWindowPos_4AD238

004AD23C Hi_fp_USER32_GetSystemMetrics_4AD23C

004AD240 Hi_fp_USER32_LoadImageW_4AD240

004AD244 Hi_fp_USER32_EnableWindow_4AD244

004AD248 Hi_fp_USER32_SendMessageW_4AD248

004AD24C Hi_fp_USER32_SetWindowTextW_4AD24C

004AD250 Hi_fp_USER32_IsDialogMessageW_4AD250

004AD254 Hi_fp_USER32_GetDlgItem_4AD254

004AD258 Hi_fp_USER32_PostQuitMessage_4AD258

004AD25C Hi_fp_USER32_PostMessageW_4AD25C

004AD260 Hi_fp_USER32_SetTimer_4AD260

004AD264 Hi_fp_USER32_GetWindowTextA_4AD264

004AD268 Hi_fp_USER32_GetWindowTextW_4AD268

004AD26C Hi_fp_USER32_SetWindowLongW_4AD26C

004AD270 Hi_fp_USER32_CreateDialogParamW_4AD270

004AD274 Hi_fp_USER32_UnregisterClassW_4AD274

004AD278 Hi_fp_USER32_DestroyWindow_4AD278

004AD27C Hi_fp_USER32_SetWinEventHook_4AD27C

004AD280 Hi_fp_USER32_DefWindowProcW_4AD280

004AD284 Hi_fp_USER32_PeekMessageW_4AD284

004AD288 Hi_fp_USER32_GetMessageW_4AD288

004AD28C Hi_fp_USER32_TranslateMessage_4AD28C

004AD290 Hi_fp_USER32_DispatchMessageW_4AD290

004AD294 Hi_fp_USER32_ShowWindow_4AD294

004AD298 Hi_fp_USER32_CharNextW_4AD298

004AD29C Hi_fp_USER32_GetWindowLongA_4AD29C

004AD2A0 Hi_fp_USER32_MonitorFromWindow_4AD2A0

004AD2A8 Hi_fp_WINMM_waveOutGetPosition_4AD2A8

004AD2AC Hi_fp_WINMM_waveOutOpen_4AD2AC

004AD2B0 Hi_fp_WINMM_waveOutPrepareHeader_4AD2B0

004AD2B4 Hi_fp_WINMM_waveOutReset_4AD2B4

004AD2B8 Hi_fp_WINMM_waveOutUnprepareHeader_4AD2B8

004AD2BC Hi_fp_WINMM_waveOutWrite_4AD2BC

004AD2C0 Hi_fp_WINMM_waveOutClose_4AD2C0

004AD2C8 Hi_fp_ole32_CoTaskMemRealloc_4AD2C8

004AD2CC Hi_fp_ole32_CoTaskMemAlloc_4AD2CC

004AD2D0 Hi_fp_ole32_CoCreateInstance_4AD2D0

004AD2D4 Hi_fp_ole32_CoInitialize_4AD2D4

004AD2D8 Hi_fp_ole32_CoUninitialize_4AD2D8

004AD2DC Hi_fp_ole32_CoTaskMemFree_4AD2DC

004B3044 Hi_self_cookie

004B37B4 Hi_dllnameArraySize

004B37BC Hi_StartEntryRVA

004B37C0 Hi_VA2

004B37C4 Hi_decxorFourTor

004B37C8 Hi_CntB1h_of_VAM_2C4h_as_dwArray

004B37CC Hi_VA3_for_bwns_SEG

004B37D0 Hi_decxorFourTor_forFuncName

004B37D4 Hi_OFFSET_VA2_to_bwns

004B37D8 Hi_RVA1_for_idata

004B37DC Hi_RVA4

004B37E0 Hi_RVA1_size

004B37E4 Hi_RVA2

004B8690 Hi_Init_for_Hi_VAM1_2C4h_asFuncTable

004B8A20 Hi_Init_kernel_functionPtrs

004B8B00 Hi_get_fp_of_GetProcAddress

004B8BC0 Hi_self_cookie_check

004C38CC Hi_ExitProcess

004C38D0 Hi_VirtualAlloc

004C38D4 Hi_VirtualProtect

004C38D8 Hi_GetModuleHandleA

004C38DC Hi_LoadLibraryA

004C38E0 Hi_GetProcAddress

004C38E4 Hi_VAM1_2C4h_asFuncTable

004C38E8 Hi_initD

004C38EC Hi_init3

004C38F0 Hi_Init7

004C38F4 Hi_curModuleHandle

004C38F8 Hi_StartEntryVA

004B84F3 call Hi_Init_kernel_functionPtrs

函数的调用完成基本核心函数指针的获取工作

.bwns:004B8A4C mov     esi, [ebp+loc_hKernel32]

.bwns:004B8A4F call    Hi_get_fp_of_GetProcAddress

.bwns:004B8A54 push    offset aLoadlibrarya ; "LoadLibraryA"

.bwns:004B8A59 push    esi

.bwns:004B8A5A mov     ds:Hi_GetProcAddress, eax

.bwns:004B8A5F call    eax

.bwns:004B8A61 push    offset aGetmodulehandl ; "GetModuleHandleA"

.bwns:004B8A66 push    esi

.bwns:004B8A67 mov     ds:Hi_LoadLibraryA, eax

.bwns:004B8A6C call    ds:Hi_GetProcAddress

.bwns:004B8A72 push    offset aVirtualprotect ; "VirtualProtect"

.bwns:004B8A77 push    esi

.bwns:004B8A78 mov     ds:Hi_GetModuleHandleA, eax

.bwns:004B8A7D call    ds:Hi_GetProcAddress

.bwns:004B8A83 push    offset aExitprocess ; "ExitProcess"

.bwns:004B8A88 push    esi

.bwns:004B8A89 mov     ds:Hi_VirtualProtect, eax

.bwns:004B8A8E call    ds:Hi_GetProcAddress

.bwns:004B8A94 push    offset aVirtualalloc ; "VirtualAlloc"

.bwns:004B8A99 push    esi

.bwns:004B8A9A mov     ds:Hi_ExitProcess, eax

.bwns:004B8A9F call    ds:Hi_GetProcAddress

.bwns:004B8AA5 push    0

.bwns:004B8AA7 mov     ds:Hi_VirtualAlloc, eax

.bwns:004B8AAC call    ds:Hi_GetModuleHandleA

.bwns:004B8AB2 mov     ds:Hi_curModuleHandle, eax

.bwns:004B8AB7 mov     eax, ds:Hi_CntB1h_of_VAM_2C4h_as_dwArray

.bwns:004B8ABC push    40h

.bwns:004B8ABE push    3000h

.bwns:004B8AC3 shl     eax, 2

.bwns:004B8AC6 push    eax

.bwns:004B8AC7 push    0

.bwns:004B8AC9 call    ds:Hi_VirtualAlloc

.bwns:004B8ACF pop     edi

.bwns:004B8AD0 mov     ds:Hi_VAM1_2C4h_asFuncTable, eax

.bwns:004B8AD5 mov     ds:Hi_Init7, 7

.bwns:004B8ADF mov     ds:Hi_init3, 3

.bwns:004B8AE9 mov     ds:Hi_initD, 0Dh

Hi_CntB1h_of_VAM_2C4h_as_dwArray 是导入表被隐藏保护的函数个数

004B8537 call    Hi_Init_for_Hi_VAM1_2C4h_asFuncTable

调用完成导入表机制的重构,使用了二级跳板机制,机制内部对函数指针做了加密,

也就导致了直接使用ImportREC是没法完成IAT修复。

al = 0

rb = c_ubyte(0)

xorFourTor = [0x16, 0x0A9, 0xD8, 0x2E]

for i in xrange(0,0x5D):

  rb.value = GetOriginalByte(0x4b2aa5+i)

  if rb.value == 0:

    al = 0

    PatchByte(0x4b2aa5+i,rb.value)

  else:

    rb.value = (rb.value>>2)|(rb.value<<6)

    rb.value = rb.value ^ xorFourTor[al&3]

    al += 1

    rb.value = rb.value ^ al

    PatchByte(0x4b2aa5+i,rb.value)

通过上述IDAPython脚本,我们可以得到加密的dll模块名称列表

这里我们是静态分析,动态调试需在在敏感点下断,

否则得不到这些解密的内容,因为完成IAT二级跳机制后,这些模块名称,

也包括后面的函数名称都会被擦除。

.bwns:004B2AA5 aWinmmDll       db 'WINMM.dll',0

.bwns:004B2AAF aKernel32Dll_0  db 'KERNEL32.dll',0

.bwns:004B2ABC aUser32Dll      db 'USER32.dll',0

.bwns:004B2AC7 aAdvapi32Dll_0  db 'ADVAPI32.dll',0

.bwns:004B2AD4 aOle32Dll       db 'ole32.dll',0

.bwns:004B2ADE aOleaut32Dll    db 'OLEAUT32.dll',0

.bwns:004B2AEB aComctl32Dll    db 'COMCTL32.dll',0

.bwns:004B2AF8 aPsapiDll       db 'PSAPI.DLL',0

在 H_VA4   ; 4c6000处,是每个导入函数的描述信息块

每个信息块大小为0x10,共0xB1个导入函数

函数信息块用来加载函数的基本逻辑如下

if FuncInfoBlock.00hb & 1 == 0:

  if 0 == hM=GetModuleHandleA(0x4b2aa5+FuncInfoBlock.04hww):

    hM=LoadLibraryA(0x4b2aa5+FuncInfoBlock.04hww)

  lpszfn = 0x004B2000+FuncInfoBlock.0Chww

  xordecfn(lpszfn)

  fp = GetProcAddress(hM,lpszfn)

  memset(lpszfn,0,len of lpszfn)

else:

  if 0 == hM=GetModuleHandleA(0x4b2aa5+FuncInfoBlock.04hww):

    hM=LoadLibraryA(0x4b2aa5+FuncInfoBlock.04hww)

  fp = GetProcAddress(hM,FuncInfoBlock.00hww >> 1)

FuncInfoBlock{

  +00h  若低位为1,则高31位为导入函数的函数索引号

  +04h  这个是指向函数所属模块的名称偏移,相对前面的模块列表首地址 004B2AA5 而言

  +08h  这个是原IAT函数地址,未加壳时,此指向地址存放导入函数地址

  +0Ch  指向以函数名称导入的(+.00hb低位为1时)函数名称在0x004B2000处的偏移

}

def xordecfn(ea):

  Hi_decxorFourTor_forFuncName=[0xcd,0x9b,0xc7,0xe4]

  al = 0

  rb = c_ubyte(0)

  while True:

    rb.value = GetOriginalByte(ea)

    if rb.value == 0:

      break

    else:

      rb.value = (rb.value>>3)|(rb.value<<5)

      rb.value = rb.value ^ Hi_decxorFourTor_forFuncName[al&3]

      al += 1

      rb.value = rb.value ^ al

      PatchByte(ea,rb.value)

    ea+=1

for i in xrange(0,0xb1):

  edi = i*0x10

  FuncInfoBlock = 0x4c6000 + edi

  mn = GetString(0x4b2aa5+Dword(FuncInfoBlock+0x04),-1,ASCSTR_C)

  fn = Dword(FuncInfoBlock)

  if (fn&1) != 0:

    fn = fn >> 1

    print '  0x{:02X}:"{}[{}]",'.format(i,mn[:-4],fn)

  else:

    lpszfn = 0x004B2000+Dword(FuncInfoBlock+0x0C)

    #print "{}: {:X}".format(mn,lpszfn)

    xordecfn(lpszfn)

    fn =  GetString(lpszfn,-1,ASCSTR_C)

    print '  0x{:02X}:"{}.{}",'.format(i,mn[:-4],fn)

    #da_bytes.create_strlit(lpszfn,fn.__len__()+1,0)

通过上述IDAPython脚本我们得以解密得到加壳前原地址表对应的模块函数列表

其中我们对两个函数索引导入的更改为相应名称的形式

这个可以直接用MS编译器工具查询,如

dumpbin /exports oleaut32.dll | find /i " 277 "

dumpbin /exports oleaut32.dll | find /i " 6 "

  #0x1C:"OLEAUT32[277]",

  0x1C:"OLEAUT32.VarUI4FromStr",

  #0x90:"OLEAUT32[6]",

  0x90:"OLEAUT32.SysFreeString",

Hi_VAM1_2C4h_asFuncTable={

  0x00:"WINMM.waveOutWrite",

  0x01:"USER32.GetWindowLongW",

  0x02:"USER32.GetClientRect",

  0x03:"KERNEL32.CompareStringW",

  0x04:"KERNEL32.GetConsoleCP",

  0x05:"KERNEL32.GetACP",

  0x06:"PSAPI.GetModuleInformation",

  0x07:"KERNEL32.DeleteCriticalSection",

  0x08:"KERNEL32.InterlockedFlushSList",

  0x09:"KERNEL32.InterlockedPushEntrySList",

  0x0A:"KERNEL32.IsValidLocale",

  0x0B:"ole32.CoUninitialize",

  0x0C:"ADVAPI32.RegSetValueExW",

  0x0D:"KERNEL32.GetDateFormatW",

  0x0E:"KERNEL32.HeapAlloc",

  0x0F:"KERNEL32.FindNextFileW",

  0x10:"USER32.MessageBoxW",

  0x11:"KERNEL32.GetThreadContext",

  0x12:"KERNEL32.LCMapStringW",

  0x13:"KERNEL32.SetStdHandle",

  0x14:"KERNEL32.GetModuleFileNameA",

  0x15:"KERNEL32.FindFirstFileExA",

  0x16:"WINMM.waveOutOpen",

  0x17:"KERNEL32.CreateFileW",

  0x18:"KERNEL32.GetCommandLineA",

  0x19:"KERNEL32.GetModuleHandleW",

  0x1A:"KERNEL32.RtlUnwind",

  0x1B:"KERNEL32.MultiByteToWideChar",

  #0x1C:"OLEAUT32[277]",

  0x1C:"OLEAUT32.VarUI4FromStr",

  0x1D:"KERNEL32.ReadFile",

  0x1E:"KERNEL32.GetFileType",

  0x1F:"USER32.SetWindowTextW",

  0x20:"KERNEL32.InterlockedIncrement",

  0x21:"KERNEL32.ResetEvent",

  0x22:"USER32.GetParent",

  0x23:"KERNEL32.FindResourceW",

  0x24:"KERNEL32.GetConsoleMode",

  0x25:"KERNEL32.IsDebuggerPresent",

  0x26:"KERNEL32.VirtualFree",

  0x27:"USER32.MessageBoxTimeoutW",

  0x28:"KERNEL32.EnterCriticalSection",

  0x29:"KERNEL32.RaiseException",

  0x2A:"KERNEL32.GetTimeFormatW",

  0x2B:"KERNEL32.WaitForSingleObject",

  0x2C:"KERNEL32.IsProcessorFeaturePresent",

  0x2D:"KERNEL32.lstrcatA",

  0x2E:"USER32.ShowWindow",

  0x2F:"KERNEL32.TlsFree",

  0x30:"KERNEL32.VirtualAlloc",

  0x31:"KERNEL32.GetStdHandle",

  0x32:"KERNEL32.InitializeSListHead",

  0x33:"KERNEL32.CreateFileA",

  0x34:"KERNEL32.ExitProcess",

  0x35:"USER32.DefWindowProcW",

  0x36:"KERNEL32.WriteFile",

  0x37:"KERNEL32.SetEvent",

  0x38:"KERNEL32.InitializeCriticalSection",

  0x39:"KERNEL32.LoadResource",

  0x3A:"KERNEL32.SetFilePointer",

  0x3B:"USER32.DestroyWindow",

  0x3C:"USER32.GetWindow",

  0x3D:"ole32.CoTaskMemRealloc",

  0x3E:"USER32.PostMessageW",

  0x3F:"ole32.CoInitialize",

  0x40:"USER32.KillTimer",

  0x41:"KERNEL32.GetCPInfo",

  0x42:"WINMM.waveOutGetPosition",

  0x43:"USER32.SendMessageW",

  0x44:"KERNEL32.HeapDestroy",

  0x45:"KERNEL32.HeapFree",

  0x46:"KERNEL32.FreeLibrary",

  0x47:"KERNEL32.SetEndOfFile",

  0x48:"ole32.CoCreateInstance",

  0x49:"KERNEL32.GetProcessHeap",

  0x4A:"ole32.CoTaskMemFree",

  0x4B:"USER32.IsDialogMessageW",

  0x4C:"USER32.PostQuitMessage",

  0x4D:"ole32.CoTaskMemAlloc",

  0x4E:"KERNEL32.InterlockedPopEntrySList",

  0x4F:"KERNEL32.IsValidCodePage",

  0x50:"ADVAPI32.RegOpenKeyExW",

  0x51:"KERNEL32.GetSystemTimeAsFileTime",

  0x52:"USER32.CreateDialogParamW",

  0x53:"KERNEL32.OutputDebugStringA",

  0x54:"USER32.TranslateMessage",

  0x55:"KERNEL32.ReadConsoleW",

  0x56:"KERNEL32.GetCurrentThread",

  0x57:"KERNEL32.lstrcmpiW",

  0x58:"KERNEL32.WaitForSingleObjectEx",

  0x59:"KERNEL32.GetUserDefaultLangID",

  0x5A:"USER32.SetWindowLongW",

  0x5B:"KERNEL32.GetCurrentProcess",

  0x5C:"KERNEL32.TlsGetValue",

  0x5D:"WINMM.waveOutReset",

  0x5E:"KERNEL32.GetStringTypeW",

  0x5F:"KERNEL32.FlushFileBuffers",

  0x60:"USER32.MapWindowPoints",

  0x61:"USER32.GetWindowTextA",

  0x62:"KERNEL32.SetUnhandledExceptionFilter",

  0x63:"KERNEL32.EncodePointer",

  0x64:"KERNEL32.SetLastError",

  0x65:"KERNEL32.GetModuleFileNameW",

  0x66:"KERNEL32.SetEnvironmentVariableA",

  0x67:"ADVAPI32.RegDeleteKeyW",

  0x68:"KERNEL32.TlsSetValue",

  0x69:"USER32.MonitorFromWindow",

  0x6A:"USER32.LoadImageW",

  0x6B:"KERNEL32.OutputDebugStringW",

  0x6C:"ADVAPI32.RegCreateKeyExW",

  0x6D:"WINMM.waveOutClose",

  0x6E:"USER32.UnregisterClassW",

  0x6F:"KERNEL32.SetThreadPriority",

  0x70:"USER32.CharNextW",

  0x71:"ADVAPI32.RegEnumKeyExW",

  0x72:"KERNEL32.GetOEMCP",

  0x73:"KERNEL32.FindClose",

  0x74:"KERNEL32.GetModuleHandleExW",

  0x75:"USER32.GetMonitorInfoW",

  0x76:"KERNEL32.FindResourceA",

  0x77:"USER32.SetTimer",

  0x78:"KERNEL32.HeapCreate",

  0x79:"KERNEL32.DecodePointer",

  0x7A:"KERNEL32.lstrlenA",

  0x7B:"USER32.GetWindowTextW",

  0x7C:"KERNEL32.UnhandledExceptionFilter",

  0x7D:"KERNEL32.LoadLibraryExW",

  0x7E:"KERNEL32.LoadLibraryExA",

  0x7F:"KERNEL32.HeapSize",

  0x80:"KERNEL32.FlushInstructionCache",

  0x81:"KERNEL32.WriteConsoleW",

  0x82:"KERNEL32.CloseHandle",

  0x83:"KERNEL32.SetEnvironmentVariableW",

  0x84:"USER32.GetWindowLongA",

  0x85:"KERNEL32.GetEnvironmentStringsW",

  0x86:"KERNEL32.CreateEventW",

  0x87:"ADVAPI32.RegQueryInfoKeyW",

  0x88:"ADVAPI32.RegCloseKey",

  0x89:"USER32.GetSystemMetrics",

  0x8A:"KERNEL32.SizeofResource",

  0x8B:"KERNEL32.GetCurrentThreadId",

  0x8C:"USER32.SetFocus",

  0x8D:"KERNEL32.FindFirstFileExW",

  0x8E:"KERNEL32.GetStartupInfoW",

  0x8F:"KERNEL32.SetFilePointerEx",

  #0x90:"OLEAUT32[6]",

  0x90:"OLEAUT32.SysFreeString",

  0x91:"KERNEL32.SetConsoleCtrlHandler",

  0x92:"KERNEL32.EnumSystemLocalesW",

  0x93:"USER32.PeekMessageW",

  0x94:"USER32.DispatchMessageW",

  0x95:"WINMM.waveOutUnprepareHeader",

  0x96:"KERNEL32.InterlockedDecrement",

  0x97:"KERNEL32.Sleep",

  0x98:"KERNEL32.TlsAlloc",

  0x99:"ADVAPI32.RegDeleteValueW",

  0x9A:"KERNEL32.HeapReAlloc",

  0x9B:"WINMM.waveOutPrepareHeader",

  0x9C:"KERNEL32.GetUserDefaultLCID",

  0x9D:"KERNEL32.InitializeCriticalSectionAndSpinCount",

  0x9E:"KERNEL32.LeaveCriticalSection",

  0x9F:"USER32.EnableWindow",

  0xA0:"USER32.SetWindowPos",

  0xA1:"KERNEL32.GetCommandLineW",

  0xA2:"KERNEL32.WideCharToMultiByte",

  0xA3:"USER32.SetWinEventHook",

  0xA4:"KERNEL32.GetProcAddress",

  0xA5:"KERNEL32.GetLocaleInfoW",

  0xA6:"KERNEL32.QueryPerformanceCounter",

  0xA7:"KERNEL32.FreeEnvironmentStringsW",

  0xA8:"COMCTL32.InitCommonControlsEx",

  0xA9:"KERNEL32.TerminateProcess",

  0xAA:"KERNEL32.GetLastError",

  0xAB:"USER32.GetMessageW",

  0xAC:"KERNEL32.FindNextFileA",

  0xAD:"KERNEL32.GetCurrentProcessId",

  0xAE:"USER32.GetWindowRect",

  0xAF:"USER32.GetDlgItem",

  0xB0:"KERNEL32.CreateThread",}

进一步,我们可以直接完成导入表函数的IDA自动重命名

for i in xrange(0,0xb1):

  edi = i*0x10

  FuncInfoBlock = 0x4c6000 + edi

  VA = 0x400000 + Dword(FuncInfoBlock+0x08)

  print "{:X} {}".format(VA,Hi_VAM1_2C4h_asFuncTable[i])

  MakeName(VA,"Hi_fp_{}_{:X}".format(Hi_VAM1_2C4h_asFuncTable[i].replace('.','_'),VA))

二级跳的导入函数机制如下

正常情况下.idata:004AD160 extrn QueryPerformanceCounter

处会存放导入函数QueryPerformanceCounter的地址,

在加壳的情况下,其存放的是混淆code-chip:VA20h1

VA20h1由VirtualAlloc动态分配,其存放下面VA20h1内容,

留意到XorEncAdd01字段存放的又是另一个code-chip:VA20h2的加密地址

加密方式是code-chip:VA20h2地址与0x20170619异或,

而code-chip:VA20h1代码就是负责解密调用code-chip:VA20h2;

在code-chip:VA20h2中,注意到XorEncAdd02字段,这里既是导入函数地址

的加密信息,由导入函数地址与0x19890526异或加密得到,code-chip:VA20h2

任务就是完成导入函数地址解密调用,举例如下

    VA20h2

    00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F

    E8 01 00 00 00 E9 58 EB 01 E8 B8 XorEncAdd02 EB //XorEncAdd02=fp ^ 0x19890526

    01 15 35|26 05 89 19 EB 01 FF 50 EB 02 FF 15 C3

    VA20h1

    E8 01 00 00 00 E9 58 EB 01 E8 B8 XorEncAdd01 EB //XorEncAdd01=VA20h2 ^ 0x20170619

    01 15 35|19 06 17 20 EB 01 FF 50 EB 02 FF 15 C3

    Hi_VAM1_2C4h[dwIdx]=VA20h1

如在程序的真正入口 0x4442a2 处断下,我们观察导入表QueryPerformanceCounter函数的信息,

其存放的是03650000,即QueryPerformanceCounter函数的code-chip:VA20h1,

我们将混淆去掉后如下所示,其就是解密XorEncAdd01=23710619 得到 03660000 跳转到

QueryPerformanceCounter函数的code-chip:VA20h2,接着就是

解密XorEncAdd01=6CE05A86 得到 QueryPerformanceCounter的地址跳转

.idata:004AD160 extrn QueryPerformanceCounter

QueryPerformanceCounter函数的code-chip:VA20h1

03650000   E8 01000000      CALL 03650006

03650005   90               NOP

03650006   58               POP EAX

03650007   EB 01            JMP SHORT 0365000A

03650009   90               NOP

0365000A   B8 19067123      MOV EAX,23710619

0365000F   EB 01            JMP SHORT 03650012

03650011   90               NOP

03650012   35 19061720      XOR EAX,20170619

03650017   EB 01            JMP SHORT 0365001A

03650019   90               NOP

0365001A   50               PUSH EAX

0365001B   EB 02            JMP SHORT 0365001F

0365001D   90               NOP

0365001E   90               NOP

0365001F   C3               RETN

QueryPerformanceCounter函数的code-chip:VA20h2

03660000

03660000   E8 01000000      CALL 03660006

03660005   90               NOP

03660006   58               POP EAX

03660007   EB 01            JMP SHORT 0366000A

03660009   90               NOP

0366000A   B8 865AE06C      MOV EAX,6CE05A86

0366000F   EB 01            JMP SHORT 03660012

03660011   90               NOP

03660012   35 26058919      XOR EAX,19890526

03660017   EB 01            JMP SHORT 0366001A

03660019   90               NOP

0366001A   50               PUSH EAX

0366001B   EB 02            JMP SHORT 0366001F

0366001D   90               NOP

0366001E   90               NOP

0366001F   C3               RETN

既要修复导入表,我们需将

.idata:004AD160 extrn QueryPerformanceCounter

处的code-chip:VA20h1地址替换为真实的QueryPerformanceCounter地址

我们通过IDAPython脚本生成自动修复的OD Script脚本

for i in xrange(0,0xb1):

  edi = i*0x10

  FuncInfoBlock = 0x4c6000 + edi

  VA = 0x400000 + Dword(FuncInfoBlock+0x08)

  mf = Hi_VAM1_2C4h_asFuncTable[i].split('.')

  print 'gpa "{}", "{}.dll"'.format(mf[1],mf[0])

  print 'mov [{:X}],$RESULT'.format(VA)

OD Script 脚本如下

gpa "waveOutWrite", "WINMM.dll"

mov [4AD2BC],$RESULT

gpa "GetWindowLongW", "USER32.dll"

mov [4AD220],$RESULT

...

gpa "CreateThread", "KERNEL32.dll"

mov [4AD0AC],$RESULT

;gpa "p", "p.dll"

;mov [4AD2E4],$RESULT

注意到最后的

;gpa "p", "p.dll"

;mov [4AD2E4],$RESULT

我们通过//cl  /EHsc p.cpp  /link /DEF:p.def /DLL /OUT:p.dll编译命令得到

一个导出p函数的p模块,p函数为空操作 retn

用于修复一下函数调用

.idata:004AD2E4 off_4AD2E4      dd offset nullsub_8

.text:0044493A nullsub_8 proc near

.text:0044493A retn

.text:4493A nullsub_8 endp

由于最终off_4AD2E4还用于保护检测,所以完成修复后,还需将setnz al,修改为 setz al,

即用CFF Explorer 将0F 95 C0 修改为0F 94 C0

.text:0044493B __guard_icall_checks_enforced:

.text:0044493B 8B 0D E4 D2 4A 00                             mov     ecx, ds:__imp_p

.text:00444941 33 C0                                         xor     eax, eax

.text:00444943 81 F9 3A 49 44 00                             cmp     ecx, offset nullsub_25

.text:00444949 0F 95 C0                                      setnz   al

.text:0044494C C3                                            retn

文件名 p.cpp

#include <windows.h>

void p(void){;} //for CFF add importer 

BOOL APIENTRY DllMain(HMODULE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved)

{

         switch (ul_reason_for_call)

         {

         case DLL_PROCESS_ATTACH:

        break ;

         case DLL_THREAD_ATTACH:

         case DLL_THREAD_DETACH:

        break ;

         case DLL_PROCESS_DETACH:

                   break;

         }

         return TRUE;

}

文件名fileName p.def

LIBRARY   p

EXPORTS 

   p @1

有了上述OD Script脚本和p.dll,我们就可以尝试脱壳

先用CFF Explorer 将p.dll模块添加到样例中,让程序启动时自动加载p模块

也可以用OD Script加载p模块的方式

然后我们断在入口点4442A2

运行上述OD Script 脚本修复IAT,然后dump出程序CTF09.exe

紧接着用Import REC附加被OD调试的样例

在IAT Infos needed处

设置 OEP 000442A2

设置 RVA 000AD000

然后Get Imports获取导入表

导入表由于模块间代理导入等原因,会出现NO的情形,

这时候我们只需对照我们已经重命名的IDA中的导入函数信息修正即可

如ImportREC提示的下述地址的导入表函数并不是ole32模块的相应函数

这时,我们只需对照我们上述得到的下述模块函数信息修正即可

.idata:004AD2CC Hi_fp_ole32_CoTaskMemAlloc_4AD2CC dd 0                                   ; .text:00413E8C↑r ...

.idata:004AD2D0 Hi_fp_ole32_CoCreateInstance_4AD2D0 dd 0

.idata:004AD2D4 Hi_fp_ole32_CoInitialize_4AD2D4 dd 0   

.idata:004AD2D8 Hi_fp_ole32_CoUninitialize_4AD2D8 dd 0

.idata:004AD2DC Hi_fp_ole32_CoTaskMemFree_4AD2DC dd

修正Imported Function Found信息后,在New Import Infos设置项里,

我们设置RVA AD000,选中Add new secio

最后fix Dump选择OD dump出的样例 CTF09.exe进行修复。

至此,再把修复的放进另一个IDA里进行分析或调试,就清净多了。

也即算完成壳的初步脱去。



附加脱壳版样例,IDA 7.0
最新回复 (4)
14
不问年少 2017-11-12 06:38
2
强悍!整个壳就想看看怎么脱的,没想到这么快就破掉了。佩服。我起的名为“防仙罩”,你这是拿来了“照妖镜”!
18
lelfei 2017-11-12 08:14
3
不算是壳了,应该说是一个Loader,负责把api地址改到二重跳的内存空间中,只需要patch二处就能直接把api填回到iat中
14
不问年少 2017-11-12 10:04
4
嗯,其实只是为了蒙住IDA的眼睛。
聖blue 2017-11-12 20:56
5
不错!
返回