資安新手,
把自己的解題過程記錄下來避免失憶症發作 lol
有錯誤的地方請大佬用力的噴我,想學到更多。
.
今天要來玩的是以二進制為取向的pwnable.kr
由於非本科,組合語言自學的關係
接觸跟組合語言有關的每次都要跟腦子大戰
如果有觀念錯誤的地方也煩請糾正我,謝謝!
對於pwn系列我想要以思考的過程為主,
因為我對二進制很生疏,
不想直接按F5生原始碼直接點出此題要怎麼解,
並且把追蹤程式碼的過程也記錄下來,
預計整篇篇幅會很大,分成上下篇。
上篇注重於程式分析,
下篇注重於漏洞利用。
題目網址:https://pwnable.kr/play.php
首先看看題目頁面
看來這次沒有給原始碼,但是有給檔案可以讓我們在自己的電腦上進行分析。
首先上IDA進行靜態分析(我沒有Pro QQ)
看main架構圖(之後會分頭進行詳細探討)
分析:
push ebp
mov esp, esp
and esp, 0FFFFFFF0h
sub esp, 40h
很基本的函數起始,對齊,跟分配local空間,不多說。
mov dword ptr [esp+8], 1Eh
mov dword ptr [esp+4], 0
lea eax, [esp+1Eh]
mov [esp], eax
call _memset
按照老標準,參數由右往左依序入棧。
在這裡注意到lea eax, [esp+1Eh]
我們把[esp+1Eh]的值設成 var1
五行下來得到 ↓
變數var1宣告; (有大神能告訴我IDA pro怎麼知道此變數型態的嗎)
memset( &var1, 0, 30 );
mov eax, stdout
mov dword ptr [esp+0Ch], 0
mov dword ptr [esp+8], 2
mov dword ptr [esp+4], 0
mov [esp], eax
call setvbuf
得到 ↓
setbuf( stdout, 0, 2, 0 );
mov eax, stdin
mov dword ptr [esp+0Ch], 0
mov dword ptr [esp+8], 1
mov dword ptr [esp+4], 0
mov [esp], eax
call setvbuf
得到 ↓
setbuf( stdin, 0, 1, 0 );
mov dword ptr [esp], offset aAuthenticate ; "Authenticate : "
call printf
得到 ↓
printf( "Authenticate :" );
lea eax, [esp+1Eh]
mov [esp+4], eax
mov dword ptr [esp], offset a30s ; "%30s"
call __isoc99_scanf
注意到[esp+1Eh]了嗎?正是上面宣告過的變數!
得到 ↓
scanf( "%30s", &var1 );
mov dword ptr [esp+8], 0Ch
mov dword ptr [esp+4], 0
mov dword ptr [esp], offset input
call _memset
這裡的input就是程式要我們鍵盤輸入的地方
得到 ↓
memset( &input, 0, 12 );
mov dword ptr [esp+18h], 0
設[esp+18h]為變數var2 ↓
變數var2宣告;
lea eax, [esp+18h]
mov [esp+4], eax
lea eax, [esp+1Eh]
mov [esp], eax
call Base64Decode
得到 ↓
Base64Decode( &var1, &var2 );
mov [esp+3Ch], eax
cmp dword ptr [esp+3Ch], 0Ch
ja short loc_8049413
eax為Base64Decode解碼後返回的長度
若長度大於12的話則跳轉到Wrong Length
否則會進到main下半部的左方這裡
mov eax, [esp+18h]
mov edx, [esp+3Ch]
mov [esp+8], edx
mov [esp+4], eax
mov dword ptr [esp], offset input
call memcpy
這裡[esp+3Ch]也同之前的變數一樣
設為 var3
得到 ↓
宣告var3
memcpy( &input, var1, var3 )
mov eax, [esp+3Ch]
mov [esp], eax
call auth
cmp eax, 1
jnz short loc_804941F
把var3 當作auth()的參數傳入
如果返回值(eax)等於就不跳轉
if( auth(var3) == 1 ) correct();
mov eax, [ebp+arg_0]
mov [esp+8], eax
mov dword ptr [esp+4], offset input
lea eax, [ebp+var_14]
add eax, 0Ch
mov [esp], eax
call memcpy
開頭基本略過,
宣告變數:
local1 ( [ebp-8] )
memcpy( &local1, &input, var3 ); # var3就是main傳過來的參數
等等!?var3 ,也就是input的長度最大不是可以等於12byte嗎?
local1距離ebp只有8byte欸?!
Um..........你想的跟我一樣嗎?
mov dword ptr [esp+4], 0Ch
lea eax, [ebp+var_14]
mov [esp], eax
call calc_md5
mov [ebp+var_C], eax
得到 ↓
變數宣告 local2 ( ebp-14h )
變數宣告 local3 ( ebp-0Ch )
local3 = calc_md5( &local2, 12 )
mov [ebp+var_C], eax
mov eax, [ebp+var_C]
mov [esp+4], eax
mov dword ptr [esp], offset aHashS ; "hash : %s\n"
call printf
得到 ↓
printf( "hash %s", local3 );
這裡合在一起講比較妥當:
得到如下 ↓
> if( strcmp( "f87cd601aa7fedca99018a8be88eda34", local3 ) == 0 ){
> return 1;
> } // if
> else return 0;
至此auth()分析結束......
int main(int argc, const char **argv, const char **envp)
{
int var2;
int16 var1;
unsigned int var3;
memset(&var1, 0, 30);
setvbuf(stdout, 0, 2, 0);
setvbuf(stdin, 0, 1, 0);
printf("Authenticate : ");
_isoc99_scanf("%30s", &var1);
memset(&input, 0, 12);
var2 = 0;
var3 = Base64Decode(&var1, &var2);
if ( var3 > 12 )
{
puts("Wrong Length");
}
else
{
memcpy(&input, var2, var3);
if ( auth(var3) == 1 )
correct();
}
return 0;
}
bool auth(int var3)
{
char local2;
char *local3;
int local1;
memcpy(&local1, &input, local3);
var3 = calc_md5(&local2, 12);
printf("hash : %s\n", local1);
return strcmp("f87cd601aa7fedca99018a8be88eda34", local3) == 0;
}
至於此程式的漏洞在哪裡,我想很清楚了。
我們下回來探討怎麼epxloit這個漏洞,取得控制權!
https://ithelp.ithome.com.tw/articles/10221639