1. 程式人生 > >南郵 逆向 ReadAsm2 wp

南郵 逆向 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}

 確實很基礎 溜了 看組合語言去惹๐·°(৹˃̵﹏˂̵৹)°·๐