下载是个elf
载入ida
观察有一段代码使用md5加密
下方有一段字符串应该为加密后的字符
再下面有个if-else语言输出是否为正常字符
对字符串进行md5解密
发现明文md5加密两次
尝试flag为grape加密一次的值
打开是个elf文件
载入ida
转化为字符
得到flag
很简单的题目
是个elf文件
载入ida
在39行处判断是否和符合的字符相等
word6020C0处的字符控制一定的顺序来对6020A0的字符操作
动态调试中程序会提取出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}'
久违的exe
PEiD载入
显示与nspack壳
脱壳机处理
手动脱壳利用ESP定律
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 以及字符串单位的换算
一个elf文件
载入ida发现是个MIPS写的
先试着打开
无法F5成伪C代码
只能先查看流程
大概是把cbtcqLUBChERV[[Nh@_X^D]X_YPV[CJ这串字符加密然后进行对比,成功就走右边,失败走下面
关键是要大概看懂MIPS汇编指令
关键就这段函数
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
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= 的位置再进去寻找
很快找到两段变换的循环
变换出来的值也显示在od内分别是
[^VZe
uYaY]`s^joY 和 idg_cni~bjbfi|gsxb
变换过程始终未出现flag.txt的字符 123456
后面就输出wrongkey
那变换的字符尝试当作flag
成功
压缩包解压后三个文件
先打开exe
PEid查壳
有个yp壳脱壳机脱壳失败
直接ida载入先看看
关键算法就这些
思路:把check_key函数过了就是变换函数
od载入
这个je是check_key函数的跳转
但是exe输出乱码
后面看其他wp里面的elf运行成功
ida远程调试
成功
题目需要补全
应该是输入flag 得到字符串
95eeaf95ef94234999582f722f492f72b19a7aaf72e6e776b57aee722fe77ab5ad9aaeb156729676ae7a236d99b1df4a
这里用gdb爆破
ida载入
一个main函数需要传入参数
在sub_804858D处设置box
在for循环中,根据传入参数输入box随机出来的数组
例如输入 “T” ascii 84 故输出box的第84个字符
思路就是先爆破找出随机的box
再根据结果字符串逆推flag
下载下来是个exe
先运行
尝试输入正确Email格式
显示错误
PEiD查壳
发现无壳
ida载入
找到主函数
最明显的就是上面一段对Email格式的判断和下面对输入的serial number的验证
根据提示还原16位serial number
尝试输入flag
成功
拿到是个exe文件
先PEiD查看无壳后ida载入
大致浏览核心部分就是两段
以及
第二部分是下半就是将flag输出
大概游戏的思路就是 根据提示输入空格 x 和 m 三个指令,最后通关
第一部分跟进函数
后面有一段判断,通过了就返回ture
查看第二部分的也是类似
不过少了提示
当时卡在这个地方,由于使用od去慢慢找有些花时间,而且看久了有点乱
后面发现可以使用ida修改判断语句
两个判断部分修改 从jnz改为jz
游戏就可以自动运行出答案
elf文件的查壳可以用 Detect it Easy 这个工具来进行
kali下使用upx命令脱壳
然后ida载入
大概思路就是传入 69800876143568214356928753 这个字符串,然后 read 函数打印进buf中,最后在lol函数内打印出来
lol函数内部
传入的那串字符相当于字典,每一位转换为ASCII码后运算即可
这题里面需要了解一下 pipe 函数实现的细节
脚本参考
https://www.cnblogs.com/DirWang/p/11451783.html