南郵 逆向 ReadAsm2 wp
題目下載連結2.asm 題目:讀彙編是逆向基本功。 給出的檔案是func函式的彙編 main函式如下 輸出的結果即為flag,格式為flag{****},請連flag{}一起提交 編譯環境為linux gcc x86-64 呼叫約定為System V AMD64 ABI 請不要利用匯編器,IDA等工具。。這裡考的就是讀彙編與推算彙編結果的能力
int main(int argc, char const *argv[]) { char input[] = {0x0, 0x67, 0x6e, 0x62, 0x63, 0x7e, 0x74, 0x62, 0x69, 0x6d,0x55, 0x6a, 0x7f, 0x60, 0x51, 0x66, 0x63, 0x4e, 0x66, 0x7b,0x71, 0x4a, 0x74, 0x76, 0x6b, 0x70, 0x79, 0x66 , 0x1c}; func(input, 28); printf(“%s\n”,input+1); return 0; }
開啟虛擬機器中的Ubuntu 把檔案放在虛擬機器中開啟 得到以下介面
00000000004004e6 < func >: //r開頭的暫存器存64位資料 e開頭的暫存器存32位資料 //↓指令對應的虛擬記憶體地址 // 計算機指令↓ 4004e6: 55 push rbp //入棧 將暫存器的值壓入呼叫bp棧中 4004e7: 48 89 e5 mov rbp,rsp //建立新的棧幀,將被調函式的棧幀棧底地址rsp放入rbp
//QWORD是四字 DWORD是雙字 一個字是2個位元組(16位) 所以QWORD儲存64位資料 DWORD儲存32位資料 PTR pointer縮寫 即指標
4004ea: 48 89 7d e8 mov QWORD PTR [rbp-0x18],rdi //在rdi [rpb-0x18]處存傳進來的第一個引數 4004ee: 89 75 e4 mov DWORD PTR [rbp-0x1c],esi //在esi [rbp-0x1c]處存傳進來的第二個引數 4004f1: c7 45 fc 01 00 00 00 mov DWORD PTR [rbp-0x4],0x1 //在記憶體[rbp-0x4]處寫入1 4004f8: eb 28 jmp 400522 < func+0x3c > //跳轉到400522處
直接分析400522處
400522: 8b 45 fc mov eax,DWORD PTR [rbp-0x4] //讀取[rbp-0x4] 所以eax=1 //條件轉移指令 cmp A,B 若A小於等於B 則執行jle指令 進行跳轉 否則不進行 400525: 3b 45 e4 cmp eax,DWORD PTR [rbp-0x1c] //比較eax與記憶體[rbp-0x1c]的值 將[rbp-0x1c] 處的值(引數2)和eax的值(引數1)作差 400528: 7e d0 jle 4004fa < func+0x14 > 40052a: 90 nop //空指令 40052b: 5d pop rbp //函式呼叫結束 彈出棧底指標 40052c: c3 ret
這些接上半部分 其實走到這我感覺下面這部分emm沒啥用了 不過還是看一下吧 0(:3 )~ (‘、3_ヽ)_
4004fa: 8b 45 fc mov eax,DWORD PTR [rbp-0x4] //eax=1 //movsxd指令為帶符號擴充套件並傳送 4004fd: 48 63 d0 movsxd rdx,eax //rdx=1 400500: 48 8b 45 e8 mov rax,QWORD PTR [rbp-0x18] //rax=input[0] 400504: 48 01 d0 add rax,rdx //rax+=rdx 400507: 8b 55 fc mov edx,DWORD PTR [rbp-0x4] //[rbp-0x4]的值給edx 40050a: 48 63 ca movsxd rcx,edx //將edx的值帶符號擴充套件,並傳送至rcx中 rcx=1 40050d: 48 8b 55 e8 mov rdx,QWORD PTR [rbp-0x18] 400511: 48 01 ca add rdx,rcx 400514: 0f b6 0a movzx ecx,BYTE PTR [rdx] 400517: 8b 55 fc mov edx,DWORD PTR [rbp-0x4] 40051a: 31 ca xor edx,ecx //edx與ecx異或 //i^input[0] 40051c: 88 10 mov BYTE PTR [rax],dl 40051e: 83 45 fc 01 add DWORD PTR [rbp-0x4],0x1 //[rbp-0x4]++
暫存器型別: ax(accumulator): 可用於存放函式返回值 bp(base pointer): 用於存放執行中的函式對應的棧幀的棧底地址 sp(stack poinger): 用於存放執行中的函式對應的棧幀的棧頂地址 ip(instruction pointer): 指向當前執行指令的下一條指令
最後再寫個小演算法就好惹(..•˘_˘•..)
C:
void func(char input[],int num) { int i = 1; while(i <= num) { *(input[0]+i) ^= i; i++; } }
Python 執行一下就出來結果了
flag{read_asm_is_the_basic}
確實很基礎 溜了 看組合語言去惹๐·°(৹˃̵﹏˂̵৹)°·๐