攻防世界|攻防世界 reverse (一)

dmd-50 下载是个elf
载入ida
攻防世界|攻防世界 reverse (一)
文章图片
观察有一段代码使用md5加密
下方有一段字符串应该为加密后的字符
攻防世界|攻防世界 reverse (一)
文章图片
再下面有个if-else语言输出是否为正常字符
对字符串进行md5解密
攻防世界|攻防世界 reverse (一)
文章图片
发现明文md5加密两次
尝试flag为grape加密一次的值
Shuffle 打开是个elf文件
载入ida
转化为字符
攻防世界|攻防世界 reverse (一)
文章图片
攻防世界|攻防世界 reverse (一)
文章图片
得到flag
很简单的题目
re2-cpp-is-awesome 是个elf文件
载入ida
攻防世界|攻防世界 reverse (一)
文章图片
在39行处判断是否和符合的字符相等
攻防世界|攻防世界 reverse (一)
文章图片

word6020C0处的字符控制一定的顺序来对6020A0的字符操作
攻防世界|攻防世界 reverse (一)
文章图片
动态调试中程序会提取出flag每个字符与输入的参数做对比
可以通过python脚本或者gdb内一个一个尝试

s1 = 'L3t_ME_T3ll_Y0u_S0m3th1ng_1mp0rtant_A_{FL4G}_W0nt_b3_3X4ctly_th4t_ ...: 345y_t0_c4ptur3_H0wev3r_1T_w1ll_b3_C00l_1F_Y0u_g0t_1t.'In [2]: s2 = [0x24, 0x0, 0x5, 0x36, 0x65, 0x7, 0x27, 0x26, 0x2d, 0x1, 0x3, 0x0, ...: 0xd, 0x56, 0x1, ...:0x3, 0x65, 0x3, 0x2d, 0x16, 0x2, 0x15, 0x3, 0x65, 0x0, 0x29, 0x44, ...: 0x44, 0x1, 0x44, 0x2b]In [3]: flag = ''In [4]: for i in range(len(s2)): ...:flag += s1[s2[i]] ...:i += 1 ...:In [5]: flag Out[5]: 'ALEXCTF{W3_L0v3_C_W1th_CL45535}'

crackme 久违的exe
PEiD载入
攻防世界|攻防世界 reverse (一)
文章图片
显示与nspack壳
脱壳机处理
手动脱壳利用ESP定律
攻防世界|攻防世界 reverse (一)
文章图片
ida载入
主要代码为
攻防世界|攻防世界 reverse (一)
文章图片

在ida内编写脚本
s='this_is_not_flag' num = 0 flag = '' for b in GetManyBytes(0x402150,168): if num%4 ==0: flag+= chr(ord(s[(num/4)%16])^ord(b)) num+=1 print flag

注意代码内的byte dword 以及字符串单位的换算
re-for-50-plz-50 一个elf文件
载入ida发现是个MIPS写的
先试着打开
攻防世界|攻防世界 reverse (一)
文章图片
无法F5成伪C代码
只能先查看流程
大概是把cbtcqLUBChERV[[Nh@_X^D]X_YPV[CJ这串字符加密然后进行对比,成功就走右边,失败走下面
关键是要大概看懂MIPS汇编指令
攻防世界|攻防世界 reverse (一)
文章图片
关键就这段函数
addiu 和 addu 相当于 add 最后存储与首个寄存器
lb 和 lw 就是加载和寻址
beq 就是 cmp + jmp
然后中间一个xori ,估计是把字符异或加密
脚本尝试
In [1]: s = 'cbtcqLUBChERV[[Nh@_X^D]X_YPV[CJ'In [2]: flag = ''In [3]: for i in range(len(s)): ...:flag += chr( ord( s[i] ) ^ 0x37 ) ...:i += 1 In [4]: flag

得到flag
key 打开是个exe
PEid查壳
攻防世界|攻防世界 reverse (一)
文章图片
无壳
ida载入
int sub_401100() { signed int v0; // esi signed int v1; // esi unsigned int v2; // edi void **v3; // ebx void **v4; // eax int v5; // ecx int v6; // ST04_4 int v7; // ST08_4 int v8; // ST0C_4 int v9; // eax int v10; // ST0C_4 char *v11; // esi int v12; // ecx void **v13; // eax int v14; // eax int v15; // ST0C_4 int v16; // eax int v17; // ST0C_4 int v18; // eax int v19; // ST0C_4 int v20; // eax int v21; // ST0C_4 int v22; // eax int v23; // ST0C_4 int v24; // eax int v25; // ST0C_4 int v26; // eax int v27; // ST0C_4 int v28; // eax int result; // eax int v30; // [esp-4h] [ebp-13Ch] int Dst; // [esp+14h] [ebp-124h] char v32[4]; // [esp+20h] [ebp-118h] char v33; // [esp+24h] [ebp-114h] int v34; // [esp+5Ch] [ebp-DCh] char v35; // [esp+61h] [ebp-D7h] int v36; // [esp+64h] [ebp-D4h] int v37; // [esp+68h] [ebp-D0h] char v38; // [esp+6Ch] [ebp-CCh] FILE *File; // [esp+70h] [ebp-C8h] char v40; // [esp+84h] [ebp-B4h] void *v41; // [esp+CCh] [ebp-6Ch] int v42; // [esp+DCh] [ebp-5Ch] unsigned int v43; // [esp+E0h] [ebp-58h] void *v44; // [esp+E4h] [ebp-54h] int v45; // [esp+F4h] [ebp-44h] unsigned int v46; // [esp+F8h] [ebp-40h] void *Memory[4]; // [esp+FCh] [ebp-3Ch] int v48; // [esp+10Ch] [ebp-2Ch] unsigned int v49; // [esp+110h] [ebp-28h] __int128 v50; // [esp+114h] [ebp-24h] __int16 v51; // [esp+124h] [ebp-14h] char v52; // [esp+126h] [ebp-12h] int v53; // [esp+134h] [ebp-4h]v46 = 15; v45 = 0; LOBYTE(v44) = 0; v53 = 0; v43 = 15; v42 = 0; LOBYTE(v41) = 0; LOBYTE(v53) = 1; v0 = 0; v48 = 1684630885; LOWORD(v49) = 97; *(_OWORD *)Memory = xmmword_40528C; // 68746164696D6568746164696D656874h v51 = 11836; v52 = 0; v50 = xmmword_4052A4; // 3C3C3C2E2E2E2E2B2B2B2B2D2D2D2D3Eh do { sub_4021E0(&v41, 1u, (*((_BYTE *)Memory + v0) ^ *((_BYTE *)&v50 + v0)) + 22); ++v0; } while ( v0 < 18 ); v1 = 0; v49 = 15; v48 = 0; LOBYTE(Memory[0]) = 0; LOBYTE(v53) = 2; v2 = v43; v3 = (void **)v41; do { v4 = &v41; if ( v2 >= 0x10 ) v4 = v3; sub_4021E0(Memory, 1u, *((_BYTE *)v4 + v1++) + 9); } while ( v1 < 18 ); memset(&Dst, 0, 0xB8u); sub_401620(&Dst, v5, v6, v7, v8); LOBYTE(v53) = 3; if ( v32[*(_DWORD *)(Dst + 4)] & 6 ) { v9 = sub_402A00(std::cerr, "?W?h?a?t h?a?p?p?e?n?", sub_402C50); std::basic_ostream>::operator<<(v9, v10); exit(-1); } sub_402E90(&Dst, &v44); v11 = &v33; if ( File ) { if ( !(unsigned __int8)sub_4022F0(&v33) ) v11 = 0; if ( fclose(File) ) v11 = 0; } else { v11 = 0; } v38 = 0; v35 = 0; std::basic_streambuf>::_Init(&v33); v36 = dword_408590; File = 0; v37 = dword_408594; v34 = 0; if ( !v11 ) std::basic_ios>::setstate((char *)&Dst + *(_DWORD *)(Dst + 4), 2, 0); v13 = Memory; if ( v49 >= 0x10 ) v13 = (void **)Memory[0]; if ( sub_4020C0(v12, v45, v13, v48) ) { v28 = sub_402A00(std::cout, "=W=r=o=n=g=K=e=y=", sub_402C50); } else { v14 = sub_402A00(std::cout, "|------------------------------|", sub_402C50); std::basic_ostream>::operator<<(v14, v15); v16 = sub_402A00(std::cout, "|==============================|", sub_402C50); std::basic_ostream>::operator<<(v16, v17); v18 = sub_402A00(std::cout, "|==============================|", sub_402C50); std::basic_ostream>::operator<<(v18, v19); v20 = sub_402A00(std::cout, "|==============================|", sub_402C50); std::basic_ostream>::operator<<(v20, v21); v22 = sub_402A00(std::cout, "\\/\\/\\/\\/\\==============|", sub_402C50); std::basic_ostream>::operator<<(v22, v23); v24 = sub_402A00(std::cout, " \\/\\/\\/\\/\\=============|", sub_402C50); std::basic_ostream>::operator<<(v24, v25); v26 = sub_402A00(std::cout, "|-------------|", sub_402C50); std::basic_ostream>::operator<<(v26, v27); std::basic_ostream>::operator<<(std::cout, sub_402C50); v28 = sub_402A00(std::cout, "Congrats You got it!", sub_402C50); } std::basic_ostream>::operator<<(v28, v30); sub_401570(&v40); std::basic_ios>::~basic_ios>(&v40); if ( v49 >= 0x10 ) sub_402630(Memory[0], v49 + 1); if ( v2 >= 0x10 ) sub_402630(v3, v2 + 1); result = v46; if ( v46 >= 0x10 ) result = sub_402630(v44, v46 + 1); return result; }

非常长的的函数
大概观察流程,对68746164696D6568746164696D656874h 和 3C3C3C2E2E2E2E2B2B2B2B2D2D2D2D3Eh两串字符进行同一种操作
然后把 C:\Users\CSAW2016\haha\flag_dir\flag.txt 这个位置的内容与操作结果对比
在od中运行
先确定输出 =W=r=o=n=g=K=e=y= 的位置再进去寻找
很快找到两段变换的循环
攻防世界|攻防世界 reverse (一)
文章图片
攻防世界|攻防世界 reverse (一)
文章图片
变换出来的值也显示在od内分别是
[^VZeuYaY]`s^joY 和 idg_cni~bjbfi|gsxb
变换过程始终未出现flag.txt的字符 123456
后面就输出wrongkey
那变换的字符尝试当作flag
成功
simple-check-100 压缩包解压后三个文件
先打开exe
PEid查壳
攻防世界|攻防世界 reverse (一)
文章图片
有个yp壳脱壳机脱壳失败
直接ida载入先看看
攻防世界|攻防世界 reverse (一)
文章图片
关键算法就这些
思路:把check_key函数过了就是变换函数
攻防世界|攻防世界 reverse (一)
文章图片
od载入
攻防世界|攻防世界 reverse (一)
文章图片

这个je是check_key函数的跳转
但是exe输出乱码
攻防世界|攻防世界 reverse (一)
文章图片
后面看其他wp里面的elf运行成功
ida远程调试
攻防世界|攻防世界 reverse (一)
文章图片
成功
reverse-box 题目需要补全
应该是输入flag 得到字符串
95eeaf95ef94234999582f722f492f72b19a7aaf72e6e776b57aee722fe77ab5ad9aaeb156729676ae7a236d99b1df4a
这里用gdb爆破
ida载入
攻防世界|攻防世界 reverse (一)
文章图片
一个main函数需要传入参数
在sub_804858D处设置box
攻防世界|攻防世界 reverse (一)
文章图片

在for循环中,根据传入参数输入box随机出来的数组
例如输入 “T” ascii 84 故输出box的第84个字符
【攻防世界|攻防世界 reverse (一)】思路就是先爆破找出随机的box
再根据结果字符串逆推flag
srm-50 下载下来是个exe
先运行
攻防世界|攻防世界 reverse (一)
文章图片

尝试输入正确Email格式
攻防世界|攻防世界 reverse (一)
文章图片
显示错误
PEiD查壳
攻防世界|攻防世界 reverse (一)
文章图片
发现无壳
ida载入
找到主函数
攻防世界|攻防世界 reverse (一)
文章图片
最明显的就是上面一段对Email格式的判断和下面对输入的serial number的验证
根据提示还原16位serial number
尝试输入flag
成功
gametime 拿到是个exe文件
先PEiD查看无壳后ida载入
大致浏览核心部分就是两段
攻防世界|攻防世界 reverse (一)
文章图片
以及
攻防世界|攻防世界 reverse (一)
文章图片
第二部分是下半就是将flag输出
大概游戏的思路就是 根据提示输入空格 x 和 m 三个指令,最后通关
第一部分跟进函数
攻防世界|攻防世界 reverse (一)
文章图片
后面有一段判断,通过了就返回ture
查看第二部分的也是类似
攻防世界|攻防世界 reverse (一)
文章图片
不过少了提示
当时卡在这个地方,由于使用od去慢慢找有些花时间,而且看久了有点乱
后面发现可以使用ida修改判断语句
两个判断部分修改 从jnz改为jz
游戏就可以自动运行出答案
攻防世界|攻防世界 reverse (一)
文章图片

easyre-153 elf文件的查壳可以用 Detect it Easy 这个工具来进行
攻防世界|攻防世界 reverse (一)
文章图片
kali下使用upx命令脱壳
攻防世界|攻防世界 reverse (一)
文章图片
然后ida载入
攻防世界|攻防世界 reverse (一)
文章图片
大概思路就是传入 69800876143568214356928753 这个字符串,然后 read 函数打印进buf中,最后在lol函数内打印出来
lol函数内部
攻防世界|攻防世界 reverse (一)
文章图片
传入的那串字符相当于字典,每一位转换为ASCII码后运算即可
这题里面需要了解一下 pipe 函数实现的细节
脚本参考
https://www.cnblogs.com/DirWang/p/11451783.html

    推荐阅读