顯示具有 Reversing and Analyzing 標籤的文章。 顯示所有文章
顯示具有 Reversing and Analyzing 標籤的文章。 顯示所有文章

2010年3月14日 星期日

2009年8月25日 星期二

另一個 call stack 還原法

http://fruitfoxlu.blogspot.com/2009/03/nt-insider-windbg3.html

Royce 大師教的 call stack 還原法

2008年7月21日 星期一

Dependency does matter


話說每一版的Milestone build前夕總免不了要爆個大問題.這次比較有趣的大概就是XXListen突然倒地不起.但時間緊迫,當時只能緊急撤掉可疑的修改讓它撐下去.但是欠債總是要還的,這版第一個build一出來,魔王又重生了


程式一執行就掛了,連first chance的call stack都讓人一頭霧水

CommandLine: C:\Builds\XXA_15.1.1007_PrivateBuild \XXListen.exe

Symbol search path is: SRV*C:\Symbols*http://myfault.kicks-ass.net;C:\PrivateBuilds\Symbols

Executable search path is: C:\Builds\XXA_15.1.1007_PrivateBuild \

ModLoad: 00400000 004f5000 XXListen.exe


(c9c.24c): Break instruction exception - code 80000003 (first chance)

eax=00351eb4 ebx=7ffda000 ecx=00000004 edx=00000010 esi=00351f48 edi=00351eb4

eip=7c92120e esp=0022fb20 ebp=0022fc94 iopl=0 nv up ei pl nz na po nc

cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202

ntdll!DbgBreakPoint:

7c92120e cc int 3

0:000> kv

ChildEBP RetAddr Args to Child

0022fb1c 7c95e612 7ffdf000 7ffda000 00000000 ntdll!DbgBreakPoint (FPO: [0,0,0])

0022fc94 7c94108f 0022fd30 7c920000 0022fce0 ntdll!LdrpInitializeProcess+0xffa (FPO: [Non-Fpo])

0022fd1c 7c92e437 0022fd30 7c920000 00000000 ntdll!_LdrpInitialize+0x183 (FPO: [Non-Fpo])

00000000 00000000 00000000 00000000 00000000 ntdll!KiUserApcDispatcher+0x7

0:000> .ecxr

Unable to get exception context, HRESULT 0x8000FFFF


原來是因為連crt的exception handler都還沒種進去就掛了,只有ntdll!_except_handler3

0022fd0c: ntdll!_except_handler3+0 (7c92e900)

CRT scope 1, filter: ntdll!_LdrpInitialize+1d5 (7c95f0f6)

func: ntdll!_LdrpInitialize+1e6 (7c95f10c)

CRT scope 0, func: ntdll!_LdrpInitialize+249 (7c95f158)


因為最外層的exception handler把現場破壞得太嚴重了,所以一定得攔在exception發生前…費盡千辛萬苦終於發現掛在這行

0:000> p

eax=0ce590be ebx=0022f78c ecx=00000000 edx=000ce590 esi=656806d0 edi=00000000

eip=65634f25 esp=0022f774 ebp=0022f9a8 iopl=0 nv up ei pl zr na pe nc

cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246

XXSOCK!XXSsockApp::InitInstance+0x155:

65634f25 68a0066865 push offset XXSOCK!g_ppszIPList (656806a0)

0:000> p

(6a0.5f4): Stack overflow - code c00000fd (first chance)

First chance exceptions are reported before any exception handling.

This exception may be expected and handled.

eax=00033018 ebx=00230000 ecx=00000002 edx=00000001 esi=002300d4 edi=00000004

eip=7c935401 esp=00033000 ebp=00033030 iopl=0 nv up ei pl zr na pe nc

cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010246

ntdll!RtlpLocateActivationContextSection+0x150:

7c935401 56 push esi


push也會出事??!! Stack明明就可讀可寫啊

00030000 : 00031000 - 001ff000

Type 00020000 MEM_PRIVATE

Protect 00000004 PAGE_READWRITE

State 00001000 MEM_COMMIT

Usage RegionUsageStack

Pid.Tid 6a0.5f4


等到冷靜下來仔細一看…不對啊…明明是單步執行怎麼一次跳好幾步? 這顯示問題不一定是那行push造成,也可能是後續被跳過無法下斷點的那幾行之一造成的.


65634eeb 8b0da0066865 mov ecx,dword ptr [XXSOCK!g_ppszIPList (656806a0)]

65634ef1 83c428 add esp,28h


0:000> p

eax=0ce590be ebx=0022f78c ecx=37fdeebe edx=000ce590 esi=656806d0 edi=00000000

eip=65634eeb esp=0022f74c ebp=0022f9a8 iopl=0 nv up ei pl nz na pe nc

cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206

TMSOCK!CTmsockApp::InitInstance+0x11b:

65634eeb 8b0da0066865 mov ecx,dword ptr [XXSOCK!g_ppszIPList (656806a0)] ds:0023:656806a0=00000000

0:000> p

eax=0ce590be ebx=0022f78c ecx=00000000 edx=000ce590 esi=656806d0 edi=00000000

eip=65634f25 esp=0022f774 ebp=0022f9a8 iopl=0 nv up ei pl zr na pe nc

cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246

TMSOCK!CTmsockApp::InitInstance+0x155:

65634f25 68a0066865 push offset TMSOCK!g_ppszIPList (656806a0)


連Windbg都不可信,正打算用OllyICE試試的時候…老天還是待我不薄,因為這時候的call stack像樣多了


00033030 7c93532a ntdll!RtlpLocateActivationContextSection+0x150

00033060 7c93528d ntdll!RtlpFindNextActivationContextSection+0x61

00033078 7c935571 ntdll!RtlpFindFirstActivationContextSection+0x41

000330c4 7c935cc9 ntdll!RtlFindActivationContextSectionString+0x8e

00033188 7c935b8a ntdll!RtlDecodeSystemPointer+0x9e7

000332f0 7c936748 ntdll!RtlDosApplyFileIsolationRedirection_Ustr+0x267

0003337c 7c936698 ntdll!LdrGetDllHandleEx+0xc9

00033398 7c80e524 ntdll!LdrGetDllHandle+0x18

000333e8 7c80e63b kernel32!GetModuleHandleForUnicodeString+0x1d

0003386c 7c80e4ec kernel32!BasepGetModuleHandleExW+0x18e

00033884 7c80b750 kernel32!GetModuleHandleW+0x29

00033890 0060c192 kernel32!GetModuleHandleA+0x2d

0003389c 0060c1e8 libNetCtrl!_decode_pointer+0x3f

000338a8 0060c30d libNetCtrl!__set_flsgetvalue+0x1e

000338b8 0060a6c8 libNetCtrl!_getptd_noexit+0x15

000338bc 0060e786 libNetCtrl!_errno+0x5

000338c4 0060c08b libNetCtrl!_get_winmajor+0x10

000338e0 0060c19d libNetCtrl!_use_encode_pointer+0x1b

000338e8 0060c1e8 libNetCtrl!_decode_pointer+0x4a

000338f4 0060c30d libNetCtrl!__set_flsgetvalue+0x1e


等等…這不太像是個call stack的起點呀… 完整的call stack呢?

00033030 7c93532a ntdll!RtlpLocateActivationContextSection+0x150

00033060 7c93528d ntdll!RtlpFindNextActivationContextSection+0x61

00033078 7c935571 ntdll!RtlpFindFirstActivationContextSection+0x41

000330c4 7c935cc9 ntdll!RtlFindActivationContextSectionString+0x8e

00033188 7c935b8a ntdll!RtlDecodeSystemPointer+0x9e7

000332f0 7c936748 ntdll!RtlDosApplyFileIsolationRedirection_Ustr+0x267

0003337c 7c936698 ntdll!LdrGetDllHandleEx+0xc9

00033398 7c80e524 ntdll!LdrGetDllHandle+0x18

000333e8 7c80e63b kernel32!GetModuleHandleForUnicodeString+0x1d

0003386c 7c80e4ec kernel32!BasepGetModuleHandleExW+0x18e

00033884 7c80b750 kernel32!GetModuleHandleW+0x29

00033890 0060c192 kernel32!GetModuleHandleA+0x2d

0003389c 0060c1e8 libNetCtrl!_decode_pointer+0x3f

000338a8 0060c30d libNetCtrl!__set_flsgetvalue+0x1e

000338b8 0060a6c8 libNetCtrl!_getptd_noexit+0x15

000338bc 0060e786 libNetCtrl!_errno+0x5

000338c4 0060c08b libNetCtrl!_get_winmajor+0x10

000338e0 0060c19d libNetCtrl!_use_encode_pointer+0x1b

000338e8 0060c1e8 libNetCtrl!_decode_pointer+0x4a

000338f4 0060c30d libNetCtrl!__set_flsgetvalue+0x1e


000fe250 0060e786 libNetCtrl!_errno+0x5

000fe258 0060c08b libNetCtrl!_get_winmajor+0x10

000fe274 0060c19d libNetCtrl!_use_encode_pointer+0x1b

000fe27c 0060c1e8 libNetCtrl!_decode_pointer+0x4a

000fe288 0060c30d libNetCtrl!__set_flsgetvalue+0x1e

000fe298 0060a6c8 libNetCtrl!_getptd_noexit+0x15


上面兩塊簡直像鬼打牆一樣出現了幾萬次,原來stack overflow是它造成的.

裡面出現了libNetCtrl!_errno,看來像是個error handler…好樣的,error handler寫出error…

讓我想到Dr.Watson crash之後又生出一個Dr.Watson前仆後繼的情景

(其作者Don Corbitt很久前就於空難中過世了,基於尊敬在下得說實話:Dr.Watson雖有小瑕疵但還是很好用)


接下來就直接攔在這個error handler的進入點,來看到底是誰造成第一個error啟動了這場災難

0022f4b4 0060a6c8 libNetCtrl!_getptd_noexit

0022f4b8 0060e786 libNetCtrl!_errno+0x5

0022f4c0 0060c08b libNetCtrl!_get_winmajor+0x10

0022f4dc 0060c126 libNetCtrl!_use_encode_pointer+0x1b

0022f4e4 0060c151 libNetCtrl!_encode_pointer+0x4a

0022f4ec 00616393 libNetCtrl!_encoded_null+0x7

0022f520 0060eaf4 libNetCtrl!__crtMessageBoxA+0xe

0022f544 00607c19 libNetCtrl!_NMSG_WRITE+0x162

0022f55c 006040e9 libNetCtrl!malloc+0x2f

0022f574 0060298b libNetCtrl!NetLocalMachine::LoadAdapters+0x19


終於找到了,不過怎麼是malloc?

00607c01 33f6 xor esi,esi

00607c03 393598fa6100 cmp dword ptr [libNetCtrl!_crtheap (0061fa98)],esi

00607c09 8bfd mov edi,ebp

00607c0b 7518 jne libNetCtrl!malloc+0x3b (00607c25)

00607c0d e8206f0000 call libNetCtrl!_FF_MSGBANNER (0060eb32)

00607c12 6a1e push 1Eh

00607c14 e8796d0000 call libNetCtrl!_NMSG_WRITE (0060e992)

00607c19 68ff000000 push 0FFh


原來是因為"libnetctrl!_crtheap"等於0,跑進了malloc裡一開頭的error handling block

0:000> dd libNetCtrl!_crtheap

0061fa98 00000000 00000000 00000000 00000000


為啥是0咧? 從VC裡附的crt source可以知道,只要_DllMainCRTStartup有被呼叫,此DLL對應的crt heap就應該被建立好了.

這麼說…_DllMainCRTStartup沒有被呼叫?


// 為說明而做了簡化,雙底線和單底線版本的差異與本主題無關,可以把它們看成一樣

#define _DllMainCRTStartup __DllMainCRTStartup

__declspec(noinline)

BOOL __cdecl

__DllMainCRTStartup(

HANDLE hDllHandle,

DWORD dwReason,

LPVOID lpreserved

)

{

if ( dwReason == DLL_PROCESS_ATTACH || dwReason == DLL_THREAD_ATTACH ) {


if ( retcode )

retcode = _CRT_INIT(hDllHandle, dwReason, lpreserved);


呼叫DllMainCRTStartup是Executable loader的責任耶…還好,之前曾經在路上撿到一份pseudo code,裡面說Loader大致是這樣運作的:


NTLoadDLL(DLL)

{

if (!AlreadyLoad(DLL) {

MapDLL(DLL);

if (IsDLL()){

RecirsivelyLoadDependencyDLL();

}

InsertDLLInitRoutineToList();

If (All_Implicitly_Linked_DLL_Loaded()) {

RunTheInitRoutineList();

}

}

}


也就是說,只有當所有隱式連結的DLL都已載入完畢時,各DLL的_DllMainCRTStartup(精確來說,是該DLL的PE header內標記的Entry point)才會被整批逐一執行.

而libNetCtrl.dll是XXListen.exe隱式連接的DLL之一,當它被XXSock.dll載入時,Loader認為XXListen.exe尚有未完全載入的DLL(libNetCtrl.dll就是其中之一囉),

所以並沒有執行libNetCtrl.dll的_ DllMainCRTStartup. 沒有Main就沒有_CRT_INIT,沒有_CRT_INIT就沒有_crtheap可以用.


這三個project之間的關係可以用下面的pseudo code來理解:

XXListen.cpp:

void main()

{

fun_in_DLL1();

fun_in_DLL2();

}


DLL1.cpp (就是XXSOck.dll):

typedef void (*_fun_in_DLL2)(void);

class _obj_in_DLL1 {

_obj_in_DLL1() {

fun_in_DLL2 = GetProcAddress(LoadLibraryA("DLL2.dll"), "fun_in_DLL2"));

fun_in_DLL2();

}

} obj_in_DLL1;

extern "C" void fun_in_DLL1(void)

{

printf("fun_in_DLL1\n");

}


與DLL2.cpp(也就是libNetCtrl.dll):

extern "C" void fun_in_DLL2(void)

{

printf("fun_in_DLL2\n");

malloc(65536);

}


然後令XXListen依賴DLL1與DLL2,但不對DLL1標記其依賴DLL2的事實

這樣等於向Loader宣稱DLL1和DLL2沒有互相依賴關係,所以該先執行誰的DllMain都可以.

若是Loader先執行DLL2的DllMain就天下太平,但若哪天它決定先執行DLL1的DllMain,問題就爆發了.

附帶一提,目前以路上撿來的那份pseudo code內容來看,

Loader將會把眾DllMain們按照他們的所屬DLL出現在Import Table內的順序,以先出現先執行的原則執行之.

倘若這行為永遠不變,還是存在一個變數,就是連結器又該如何決定兩個不互相依賴的DLL,誰該在前而誰又該在後?

總之這兩個變數就是讓這問題時而出現時而消失的元凶.

2007年12月2日 星期日

Stack, a locker without lock

A function 呼叫 B function, 並傳遞了兩個 4-byte 參數. 但當 B function 要取用的時候, 參數在 stack 裡被歸零了!




2007年12月1日 星期六

goto CLEANUP or TRAP

這幾天犯了一個嚴重的錯誤, 害 XXXNT 在 64-bit Vista 上一執行就會 GPF

void foo()
{
 if (something is wrong)
 goto CLEANUP;
 char *ptr = NULL;
 ptr = new char [100];
CLEANUP:
 if (ptr) delete [] ptr;
}

這段 code 會被編譯成:

 cmp something_is_wrong
 je CLEANUP1
 push 64h
 call operator new
 add esp,4
 jmp CLEANUP2
CLEANUP1:
 mov eax, dword ptr [esp+4]
CLEANUP2:
 test eax,eax
 je END
 push eax
 call operator delete
 add esp,4
END:
 xor eax,eax
 ret

也就是說, 假如真的執行到了 goto 指令, 則將存取到 esp+4 這塊記憶體, 而其內容並非我們所想像的 NULL, 因此將會引發不可預期的後果.

幸好, 當 VC8 的 compile warning level 開到 /W4 的時候, 這種 code 將會引發一個 C4701 warning

2007年10月14日 星期日

Kernel object deadlock hunting

這報告的知識都是取之於網路, 所以我打算回饋一下...
Kernel object deadlock hunting

當 event 或 semaphore 這種不具 ownership 紀錄的 Windows kernel object 發生 deadlock, 怎麼找出咬住該 object 的執行緒?
只要運氣夠好, 還是有機會把它揪出來!

2007年9月11日 星期二

When operator new and delete are overwritten

上個禮拜, 本 team 的強者查理大大發現了一個 Vista 上的 Crash... 其 Dump 可謂匪夷所思

我們首次到手的 Dump, call stack 長這樣:

# 1 Id: d30.fd4 Suspend: 1 Teb: 7ffde000 Unfrozen
ChildEBP RetAddr Args to Child
029fc564 773a1d37 01390000 006d5748 029fc60c ntdll!RtlpCoalesceFreeBlocks+0x26d
029fc65c 773a1c21 006d5748 006d5750 006d5750 ntdll!RtlpFreeHeap+0x1e2
029fc678 75d97a7e 01390000 00000000 006d5748 ntdll!RtlFreeHeap+0x14e
029fc68c 1000d343 01390000 00000000 006d5750 kernel32!HeapFree+0x14
029fc6cc 1000961b 006d5750 1bdb284a 029fc798 libXXXXXSecure!free+0x6e
029fc73c 10008c5a 46e56fb6 00000d30 00000fd4 libXXXXXSecure!LogWriteW+0xeb
029fe778 10008d7f 00000008 01390c08 00000154 libXXXXXSecure!vdprintfW+0x1da
029fe7a0 10008edf 00000008 01390c08 00000154 libXXXXXSecure!dprintfW+0x2f
029fe7b8 100090a8 1bdb0952 75d97b60 773a2f1d libXXXXXSecure!CDebugLogW::EnterDebugLog+0x1f
029fe7e4 10025a05 1002f274 00000154 1002f398 libXXXXXSecure!CDebugLogW::CDebugLogW+0x158
029fec40 0044bcd6 1bc66186 00000000 006ad738 libXXXXXSecure!TSECURE::clearTGPTempDir+0x45

...

3 Id: d30.51c Suspend: 1 Teb: 7ffdc000 Unfrozen
ChildEBP RetAddr Args to Child
03ebf92c 773a06a0 7737b18c 00000338 00000000 ntdll!KiFastSystemCallRet
03ebf930 7737b18c 00000338 00000000 00000000 ntdll!NtWaitForSingleObject+0xc
03ebf994 7737b071 00000000 00000000 01390000 ntdll!RtlpWaitOnCriticalSection+0x154
03ebf9bc 77368f4a 01390130 03eb9ea4 01390000 ntdll!RtlEnterCriticalSection+0x152
03ebfaa0 773a214c 00000214 00000220 0139039c ntdll!RtlpAllocateHeap+0x15c
03ebfb18 10018acb 01390000 00000008 00000214 ntdll!RtlAllocateHeap+0x1e3
03ebfb58 1001133a 00000214 00000214 00000000 libXXXXXSecure!_calloc_impl+0xc4
03ebfb70 1000daf3 00000001 00000214 00000000 libXXXXXSecure!_calloc_crt+0x13
03ebfb90 1000dbaa 10000000 00000002 00000000 libXXXXXSecure!_CRT_INIT+0x17b
03ebfbd0 1000dc64 10000000 773aa604 10000000 libXXXXXSecure!__DllMainCRTStartup+0x59
03ebfbd8 773aa604 10000000 00000002 00000000 libXXXXXSecure!_DllMainCRTStartup+0x1d
03ebfbf8 7737ab3b 1000dc47 10000000 00000002 ntdll!LdrpCallInitRoutine+0x14
03ebfc98 7737a954 03ebfd24 03eb9904 00000000 ntdll!LdrpInitializeThread+0x149
03ebfd00 7737a980 03ebfd24 77340000 00000000 ntdll!_LdrpInitialize+0x21d
03ebfd10 00000000 03ebfd24 77340000 00000000 ntdll!LdrInitializeThunk+0x10

列出這兩個 Thread 主要是因為, 我們一度以為 Vista 環境中竟然平行執行 DllMainCRTStartup 及 mainCRTStartup...

但後來發現_CRT_INIT 的 dwReason 參數, 它並非我們所想像的 DLL_PROCESS_ATTACH(1) 而是 DLL_THREAD_ATTACH(2).

03ebfb90 1000dbaa 10000000 00000002 00000000 libXXXXXSecure!_CRT_INIT+0x17b

也就是說, 這根 Thread 根本是來擾亂視聽的, 它其實正常運作中, 只不過被 crashed thread 所 own 住的 Heap lock 給卡住了而已.

所以我們似乎可以把重心全部放在 fd4 這根 thread 上.

此外, 感謝查理大的指示, 我們還擁有一個很重要的線索, 就是該 crash 的 process 會間接 include 到一個

overwrite 掉 operator new 及 delete 的 header file:

static inline void* operator new(size_t size)
{
void* ptr = ::HeapAlloc(::GetProcessHeap(), 0, size);
if (!ptr)
{
_THROW_NCEE(std::bad_alloc, "Insufficient memory");
}
return ptr;
}
static inline void operator delete(void* ptr) { ::HeapFree(::GetProcessHeap(), 0, ptr); }

我們幾乎可以確定問題一定是由它造成的, 但接下來我們想知道的是:

問題到底是怎麼造成的呢? 它真的會 overwrite 掉 CRT 當中對 operator new 及 delete 的實作嗎?

於是我們追進 crashed thread 所呼叫的 free() 當中, 可以看到它操作的是 _crtheap (由 _head_init@CRT 所建立)

libXXXXXSecure!free:
1000d2d5 6a0c push 0Ch
1000d2d7 68f8220310 push offset libXXXXXSecure!_CT??_R0?AVout_of_rangestd+0x2b8 (100322f8)
1000d2dc e837910000 call libXXXXXSecure!__SEH_prolog4 (10016418)
1000d2e1 8b7508 mov esi,dword ptr [ebp+8]
1000d2e4 85f6 test esi,esi
1000d2e6 7475 je libXXXXXSecure!free+0x88 (1000d35d)
1000d2e8 833da08d031003 cmp dword ptr [libXXXXXSecure!__active_heap (10038da0)],3
1000d2ef 7543 jne libXXXXXSecure!free+0x5f (1000d334)
1000d2f1 6a04 push 4
1000d2f3 e8ed850000 call libXXXXXSecure!_lock (100158e5)

...

1000d337 ff35f4880310 push dword ptr [libXXXXXSecure!_crtheap (100388f4)]
1000d33d ff1514b00210 call dword ptr [libXXXXXSecure!_imp__HeapFree (1002b014)]

由此可見, 該 header file 並沒有 overwrite 掉 CRT 當中的 operator delete 實作.

那 operator new 呢? 我們追進 basic_string::_Copy > basic_string::allocate > std::_Allocate > operator new,

可以看到其實作如下:

libXXXXXSecure!operator new:
10025d10 55 push ebp
10025d11 8bec mov ebp,esp
10025d13 83ec10 sub esp,10h
10025d16 8b4508 mov eax,dword ptr [ebp+8]
10025d19 50 push eax
10025d1a 6a00 push 0
10025d1c ff1518b00210 call dword ptr [libXXXXXSecure!_imp__GetProcessHeap (1002b018)]
10025d22 50 push eax
10025d23 ff1544b00210 call dword ptr [libXXXXXSecure!_imp__HeapAlloc (1002b044)]
...

很明顯地, 它是被 overwrite 掉之後的結果.

平平都是 include 那個 overwrite header file, 為啥 operator new 被蓋掉了, 但 operator delete 卻沒有?

我們展開呼叫了 operator delete 的 LogWriteW:

100095fc e8fffaffff call libXXXXXSecure!Send (10009100)
10009601 397c2448 cmp dword ptr [esp+48h],edi
10009605 8ad8 mov bl,al
10009607 c744241044bc0210 mov dword ptr [esp+10h],offset libXXXXXSecure!CCmdProtocol::`vftable' (1002bc44)
1000960f 720d jb libXXXXXSecure!LogWriteW+0xee (1000961e)
10009611 8b442434 mov eax,dword ptr [esp+34h]
10009615 50 push eax
10009616 e864350000 call libXXXXXSecure!operator delete (1000cb7f)

它理應要呼叫 CCmdProtocol::~CCmdProtocol() 來做 cleanup 動作, 但因為被 optimize 的緣故, 此處只出現了一個 delete,

而且這個 delete 忽略掉 overwrite function, 仍舊與 CRT 的實作相連結, 這應該算是個 optimization error 吧...


所謂禍不單行, 取消掉 libLogClient 的 optimization 之後, 程式仍然會 crash...

這次的 Dump, crashed thread 的 call stack 如下:

# 1 Id: 820.f94 Suspend: 1 Teb: 7ffdd000 Unfrozen
ChildEBP RetAddr Args to Child
02bfe684 773a1d37 002f0000 01670c38 02bfe72c ntdll!RtlpCoalesceFreeBlocks+0x35
02bfe77c 773a1c21 01670c38 01670c40 773a2f1d ntdll!RtlpFreeHeap+0x1e2
02bfe798 75d97a7e 002f0000 00000000 01670c38 ntdll!RtlFreeHeap+0x14e
02bfe7ac 10027f56 002f0000 00000000 01670c40 kernel32!HeapFree+0x14
02bfe7c0 10002ffa 01670c40 02bfea20 01670c40 libXXXXXSecure!operator delete+0x16
02bfe7d4 10002f7d 67c8f9a4 02bfea0c 02bfec34 libXXXXXSecure!std::auto_ptr::~auto_ptr+0x1a
02bfe7f0 10025d18 67c8f214 003a0043 0050005c libXXXXXSecure!CDebugLogW::~CDebugLogW+0x4d
02bfec40 0044bcd6 67dbc520 00000000 0031d738 libXXXXXSecure!TSECURE::clearTGPTempDir+0x1a8

出現了 auto_ptr object... 顯然又是個 new/delete 不相符造成的 crash

以同樣的方法追進去, 可以看到這次 operator delete 被 overwrite 掉了, 但 operator new 並沒有

原來是因為 CDebugLogW::~CDebugLogW 的實作放在 header file 裡, 而 CDebugLogW::CDebugLogW 的實作放在另一個 library 內.

從這個例子我們可以看到, 這種寫法會造成建解構函式分別採用到不同的 CRT function 實作.

2007年4月8日 星期日

crackme2.exe in Makkakko tutorial

下載
1. 攔 USER32!GetDlgItemTextA, 可知序號將被存入 0x0040217E.

2. 在 0x0040217E 處設存取中斷點, 可知序號將經過下列加工:
a. 所有英文小寫字母轉大寫
b. 跟 "Messing_in_bytes" 這 16 bytes 做 XOR.

3. 把 XOR 完之後的 16 bytes 跟下面 byte sequence 比對:
1f, 2c, 37, 36, 3b, 3d, 28, 19, 69, 6e, 5f, 62, 79, 74, 65, 73
若超過兩個 byte 以上相異, 則序號不合法.