南邮CTF逆向 ReadAsm2 writeup

菜鸡刚学汇编,找道逆向题练练手,详细写下怎么解题的。由于是菜鸡,写的很啰嗦。

主函数如下。
南邮CTF逆向 ReadAsm2 writeup
函数汇编代码如下
南邮CTF逆向 ReadAsm2 writeup

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++
南邮CTF逆向 ReadAsm2 writeup
输出结果即是 flag
南邮CTF逆向 ReadAsm2 writeup