首先看secret.cpp的代碼結(jié)合“From:”來進行切入。
由于前面進行的都是聲明變量,變量賦值的工作,所以從第103行開始分析。
process_key12(int * key1,int * key2)函數(shù)中*((int *) (key1 + *key1)) = *key2;
表示了將*key1
(實際變量存儲地址)的所在位置向高地址增加 *key1
的偏移量處的值賦為key2的值。當(dāng)然這和偏移量有關(guān),所以現(xiàn)在還不知道那個值被修改了。
繼續(xù)向下看源碼,發(fā)現(xiàn)start = 0, stride =1。
然后是process_key34(),查看代碼后發(fā)現(xiàn)實類似的操作,先放著。
然后開始extract_message1(start, stride)
密文的decode操作。將start = 0,stride = 1帶代入,發(fā)現(xiàn)是一個死循環(huán),所以此時start和stride的值并不對,那么如何修改呢,發(fā)現(xiàn)是process_key12()的影響,于是研究此函數(shù):
- 局部變量的生成順序是dummy,start,stride,key1,key2,由于棧是從高地址向低地址進行分配的,所以
*key
是一個正數(shù)并且process函數(shù)只能修改一個數(shù)的值而start和stride都由dummy來初始決定,所以顯而易見修改了dummy的值,所以key1的值為3(因為有dummy,start,stride三個4字節(jié)int值),接下來需要確定key2的值。 -
start = (int)(*(((char *) &dummy)));
stride = (int)(*(((char *) &dummy) + 1));
這兩段是start的賦值,可以看到先轉(zhuǎn)成char指針,在轉(zhuǎn)成int值,而char占用1字節(jié),int占用4字節(jié),所以(_ _ _ _
,表示dummy的四個字節(jié),而程序里以字節(jié)為單位來逆序排列dummy的四個字節(jié),如dummy=340,內(nèi)存內(nèi)dummy的字節(jié)序列是(低地址到高地址)15 04 00 00
,由此可以看出,不僅棧是從高地址向低地址來分配的,而且變量的字節(jié)是由高地址向低地址00000415讀取的)。 - 現(xiàn)在根據(jù)From:的ascii碼值來找,發(fā)現(xiàn)為46 72 6F 6D 3A,然后在data中查找,注意data在內(nèi)存中以4字節(jié)唯一單位,四字節(jié)內(nèi)部順序是高地址向低地址讀取,所以并不是純粹的data中的那些順序,而且data中的4字節(jié)是從最后一個開始壓進棧中的。所以加法操作后到高地址,正好可以到達(dá)data后面的字節(jié)中。
- 現(xiàn)在來看for循環(huán),i變量只是提供message[i]中i的作用,內(nèi)部變量循環(huán)stride-1次,出來后又+1,現(xiàn)在來觀察幾個字節(jié)出現(xiàn)的順序,后面的數(shù)值是距離*data的距離,即+j。
46: 9 *10* 20
72: *11* 12 21
6F: *13* 15
6D: *14* 19
3A: *16*
可以看到內(nèi)部循環(huán)為兩次,所以stride=3,start = 10 -1 =9,所以key2=0x00000309=777.
之后得到結(jié)果
From: Friend
To: You
Good! Now try choosing keys3,4 to force a call to extract2 and
avoid the call to extract1
發(fā)現(xiàn)還有第二段密文,然我們用key3和key4來繞過extract1,所以需要更改process_key34之后的返回地址。
process_key34的函數(shù)過程為*(((int *)&key3) + *key3) += *key4;
,*key3
為偏移量,此處&key3指的是形參中的key3,所以就和函數(shù)棧有關(guān)。我們知道形參是從右往左入棧的,而在形參入棧后,會把函數(shù)返回地址加上,所以函數(shù)返回地址是在key3的下面(低地址處),所以*key3
的值為-1,所以函數(shù)的返回地址增加多少才能繞過exetract_message1呢,此時我們反匯編源程序,查看exetract_message1和exetract_message2的函數(shù)地址。
0x100000ead <+253>: callq 0x100000c10 ; process_keys34 at main.c:57
0x100000eb2 <+258>: movl -0x18(%rbp), %edi
0x100000eb5 <+261>: movl -0x1c(%rbp), %esi
0x100000eb8 <+264>: callq 0x100000c40 ; extract_message1 at main.c:62
0x100000ebd <+269>: movq %rax, -0x38(%rbp)
0x100000ec1 <+273>: movq -0x38(%rbp), %rax
0x100000ec5 <+277>: movsbl (%rax), %esi
0x100000ec8 <+280>: cmpl $0x0, %esi
0x100000ece <+286>: jne 0x100000f0a ; <+346> at main.c:128
0x100000ed4 <+292>: leaq -0x28(%rbp), %rdi
0x100000ed8 <+296>: leaq -0x2c(%rbp), %rsi
0x100000edc <+300>: callq 0x100000c10 ; process_keys34 at main.c:57
0x100000ee1 <+305>: movl -0x18(%rbp), %edi
0x100000ee4 <+308>: movl -0x1c(%rbp), %esi
0x100000ee7 <+311>: callq 0x100000d30 ; extract_message2 at main.c:82
所以key4= 311 - 264 = 47。
雖然key3和key4帶進去都沒有得到正確的值,但是我盡力了。~~
綜上,key1 = 3,key2 = 777,key = -1,key4 = 47。