逆向分析
做逆向题先查壳, 就像做pwn先checksec一样
用PEid查不出来, 用Exeinfo PE可以查出ELF文件的壳
用工具直接脱upx壳, kali自带的工具或者手动安装一个windows的upx工具
脱壳之后拖入IDA32
int __cdecl main(int argc, const char **argv, const char **envp)
{int pipedes[2]; // [esp+18h] [ebp-38h] BYREF__pid_t v5; // [esp+20h] [ebp-30h]int v6; // [esp+24h] [ebp-2Ch] BYREFchar buf[30]; // [esp+2Eh] [ebp-22h] BYREFunsigned int v8; // [esp+4Ch] [ebp-4h]v8 = __readgsdword(0x14u);pipe(pipedes);v5 = fork(); // subprocess fpidif ( !v5 ) // if subprocess then execute{puts("\nOMG!!!! I forgot kid's id");write(pipedes[1], "69800876143568214356928753", 0x1Du);puts("Ready to exit ");exit(0);}read(pipedes[0], buf, 0x1Du); // subprocess input 69800876143568214356928753__isoc99_scanf("%d", &v6);if ( v6 == v5 ){if ( (unsigned __int8)*(_DWORD *)((char *)lol + 3) == 204 ){puts(":D");exit(1);}printf("\nYou got the key\n ");lol(buf);}wait(0);return 0;
}
这是一个linux系统编程的逆向, 需要fork和进程间通信的知识, 系统编程和软件开发是做逆向的基本功, 所以需要补这方面的知识, 就不多说了 (面向搜索引擎做逆向也是基本功, 什么不懂现场学就完了
首先fork()
是返回创建的子进程的进程id, 子进程fpid是0, 父进程则保存子进程的fpid, 所以下面的代码只有子进程会执行
if ( !v5 ) // if subprocess then execute{puts("\nOMG!!!! I forgot kid's id");write(pipedes[1], "69800876143568214356928753", 0x1Du);puts("Ready to exit ");exit(0);}
pipe(pipedes);
是创建父子进程之间的通信管道, pipedes[0]是读, pipedes[1]是写
read(pipedes[0], buf, 0x1Du);
即父进程从管道读取0x1D的数据到buf
缓冲区
write(pipedes[1], "69800876143568214356928753", 0x1Du);
是子进程将"69800876143568214356928753"
写入管道, 所以父进程读出来的就是这一串
跟如lol()
函数发现反编译和汇编代码不一致, 这里就是涉及IDA反汇编的优化操作, 如果一段汇编代码被强制跳转略过, 根本不会被执行, 那么IDA的F5就不会反编译这段汇编代码, 所以看到的伪代码就是一行printf
用IDApython nop掉0x080486B0
地址的汇编指令, 这里如果是IDA7.5+版本, 因为API改了, 所以需要加一句from idc_bc695 import *
再F5即可反编译完整汇编
int __cdecl lol(_BYTE *buf)
{int result; // eaxchar flag[7]; // [esp+15h] [ebp-13h] BYREFint v3; // [esp+1Ch] [ebp-Ch]flag[0] = 2 * buf[1];flag[1] = buf[4] + buf[5];flag[2] = buf[8] + buf[9];flag[3] = 2 * buf[12];flag[4] = buf[18] + buf[17];flag[5] = buf[10] + buf[21];flag[6] = buf[9] + buf[25];if ( v3 == 1 )result = printf("%s", flag);elseresult = printf("flag_is_not_here");return result;
}
破解
阅读F5出来的伪代码, 即可知道flag就是69800876143568214356928753
处理出来的7字节串, 直接用cpp写逆
#include <iostream>
#include <string>
using namespace std;int main () {string flag(7, '0');string buf = "69800876143568214356928753";flag[0] = 2 * buf[1];flag[1] = buf[4] + buf[5];flag[2] = buf[8] + buf[9];flag[3] = 2 * buf[12];flag[4] = buf[18] + buf[17];flag[5] = buf[10] + buf[21];flag[6] = buf[9] + buf[25];cout << "RCTF{" << flag << '}' << endl;
}
搞定~