菜雞剛學彙編,找道逆向題練練手,詳細寫下怎麼解題的。由于是菜雞,寫的很啰嗦。
主函數如下。
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAzNfRHLGZkRGZkRfJ3bs92YsYTMfVmepNHL5VkaOBza61keRpHW4Z0MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnLyQTNyQTOwcTM5ETMxgTMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
函數彙編代碼如下
4004e6: 55 push rbp
4004e7: 48 89 e5 mov rbp,rsp
前兩句 push rbp 将rbp壓棧,再将 rsp的值給rbp,提升堆棧的。
4004ea: 48 89 7d e8 mov QWORD PTR [rbp-0x18],rdi
4004ee: 89 75 e4 mov DWORD PTR [rbp-0x1c],esi
4004f1: c7 45 fc 01 00 00 00 mov DWORD PTR [rbp-0x4],0x1
這三句了解為參數的傳遞,和局部變量的聲明,
由後面的代碼段(後面會分析下)可以了解到 [rbp-0x4] 裡存放的值是相當于c語言的
for(int i=1;i<=28;i++)
中的 i ,
DWORD PTR [rbp-0x1c] 中存放的值是 28,控制循環次數的。
RDI 就是數組第一個元素的位址。
4004f8: eb 28 jmp 400522 <func+0x3c>
跳轉到 400522,分析下
400522: 8b 45 fc mov eax,DWORD PTR [rbp-0x4]
400525: 3b 45 e4 cmp eax,DWORD PTR [rbp-0x1c]
400528: 7e d0 jle 4004fa <func+0x14>
40052a: 90 nop
40052b: 5d pop rbp
40052c: c3 ret
第一句将 (DWORD PTR [rbp-0x4] )指派給 eax ,eax=1;
第二句 比較 eax 和( DWORD PTR [rbp-0x1c] )的大小,如果 eax 小于等于後者(28),則跳轉到4004fa ,否者 函數結束傳回。 由第二句可以知道 DWORD PTR [rbp-0x1c] 中的存放的值是 控制循環次數的
即main函數中 func(input, 28)中的28。而eax 即是 i 。
下面分析下 4004fa 處。
4004fa: 8b 45 fc mov eax,DWORD PTR [rbp-0x4] // eax =1
4004fd: 48 63 d0 movsxd rdx,eax //rdx = 1
400500: 48 8b 45 e8 mov rax,QWORD PTR [rbp-0x18]
// [rbp-0x18]中放的是數組第一個元素的位址
400504: 48 01 d0 add rax,rdx
// rax 是第二個元素的位址,用rax儲存位址,友善後面将異或的值指派給數組
400507: 8b 55 fc mov edx,DWORD PTR [rbp-0x4] //edx = 1
40050a: 48 63 ca movsxd rcx,edx
40050d: 48 8b 55 e8 mov rdx,QWORD PTR [rbp-0x18]
400511: 48 01 ca add rdx,rcx // rdx = ([rbp-0x18] )+1
//RDX 中儲存了 第二個元素的位址
400514: 0f b6 0a movzx ecx,BYTE PTR [rdx]
//ecx 中 儲存的是 數組第二個元素的值
400517: 8b 55 fc mov edx,DWORD PTR [rbp-0x4]
// i =edx=1
40051a: 31 ca xor edx,ecx
//将 第二個元素 和 1 異或
40051c: 88 10 mov BYTE PTR [rax],dl
40051e: 83 45 fc 01 add DWORD PTR [rbp-0x4],0x1
//這裡相當于 c 語言 i++
上面的注釋都是以第一次循環寫的 ,後面的依次類推。
函數功能就是将數組第二個元素到第29個元素分别和 i 進行異或 。
寫個c++
輸出結果即是 flag