getit
程式分析
使用IDA打開程式,F5鍵利用HexRay工具生成可讀代碼如下:
int __cdecl main(int argc, const char **argv, const char **envp)
{
char v3; // al
__int64 j; // [rsp+0h] [rbp-40h]
int i; // [rsp+4h] [rbp-3Ch]
FILE *stream; // [rsp+8h] [rbp-38h]
char filename[8]; // [rsp+10h] [rbp-30h]
unsigned __int64 v9; // [rsp+28h] [rbp-18h]
v9 = __readfsqword(0x28u);
LODWORD(j) = 0;
while ( (signed int)j < strlen(s) )
{
if ( j & 1 )
v3 = 1;
else
v3 = -1;
*(&t + (signed int)j + 10) = s[(signed int)j] + v3;
LODWORD(j) = j + 1;
}
strcpy(filename, "/tmp/flag.txt");
stream = fopen(filename, "w");
fprintf(stream, "%s\n", u, j);
for ( i = 0; i < strlen(&t); ++i )
{
fseek(stream, p[i], 0);
fputc(*(&t + p[i]), stream);
fseek(stream, 0LL, 0);
fprintf(stream, "%s\n", u);
}
fclose(stream);
remove(filename);
return 0;
}
從上面代碼可以看出,該程式将flag儲存在了
/tmp/flag.txt
的位置,然後作者很賤的又remove了這個檔案,是以程式執行之後看不見。
那麼,理論上隻要在remove的位置加斷點,然後在檔案被删除之前打開就行。但實際上作者特别賤,不僅挖了remove這個坑,還通過fprintf(stream, “%s\n”, u);這條語句将flag.txt檔案中的資訊用覆寫了,是以即便拿到flag.txt檔案也是沒有用的,裡面是“************”。但是無所謂,這時隻要檢視變量
t
處的記憶體就能找到flag明文。
csaw2013reversing2
程式分析
使用IDA打開程式,F5鍵利用HexRay工具生成可讀代碼如下:
int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
int v3; // ecx
CHAR *lpMem; // [esp+8h] [ebp-Ch]
HANDLE hHeap; // [esp+10h] [ebp-4h]
hHeap = HeapCreate(0x40000u, 0, 0);
lpMem = (CHAR *)HeapAlloc(hHeap, 8u, MaxCount + 1);
memcpy_s(lpMem, MaxCount, &unk_409B10, MaxCount);
if ( sub_40102A() || IsDebuggerPresent() )
{
__debugbreak();
sub_401000(v3 + 4, lpMem);
ExitProcess(0xFFFFFFFF);
}
MessageBoxA(0, lpMem + 1, "Flag", 2u);
HeapFree(hHeap, 0, lpMem);
HeapDestroy(hHeap);
ExitProcess(0);
}
閱讀代碼可知,IsDebuggerPresent()用于判斷調試器是否打開,也就是說隻有當調試器開啟的時候才會進到if語句裡面。而if裡面的sub_401000函數是解密函數,是以必須要執行這個函數才能得到正确的flag。但是,解密之後程式會ExitProcess退出,是以沒法執行MessageBoxA讓我們看到flag的結果。
這裡有兩種思路,一種是通過調試,在ExitProcess處加斷點,然後從記憶體中找到lpMem對應的flag資料。另一種是修改跳轉語句,使得sub_401000執行完之後直接跳到MessageBoxA執行。
方法1
如上圖所示設定斷點,開始調試後由于__debugbreak();的存在,調試程式會先斷在__debugbreak處,這時點繼續運作,然後選擇“否”就能斷到ExitProcess的位置。
這時滑鼠移到lpMem上方,可以看到lpMem的值是
0x26505B8
。在Hex-View視窗中按“g”鍵,輸入上面的位址值,就能看到flag。
方法2
如下圖所示是程式的跳轉關系,隻需如紅箭頭所示将jmp指令的跳轉位置修改為loc_9E10B9即可,很簡單。
在
jmp short loc_9E10EF
上右鍵選擇“keypatch->patch”,如下圖所示進行修改。修改後視窗會繼續跳轉到下一條指令,這時關閉這個視窗就行了。
然後點選“Edit->Patch Program->Apply…”将修改應用到exe檔案。
這時開調試模式運作程式就可以看到彈窗變為正确的flag了。
如果想要直接運作exe得到正常的結果,還需進行以下兩處修改:
- IsDebuggerPresent下方的jz改為jnz,相當于逆轉條件判斷後的跳轉;
- __debugbreak處會觸發中斷,會導緻正常執行時程式奔潰,将對應的彙編指令int 3改為NOP即可,NOP為空指令,不做任何操作。