https://qsnctf.com/challenges#babyUPX-328
0x00: 先吐槽下这道题。
1. 依赖MinGW环境,查了半天用了一个MinGW装的MSYS环境
2. 只要输入flag的前缀就能过
比如,
- $ babyUPX.exe
- SICTF
- Congratulations!
复制代码 所以,我们可以一位一位试(我现在还不清楚算法细节)
0x01: 脱壳
upx -d会提示文件损坏,因为UPX!标识被隐去,如图
把_改为U即可使用upx -d正常脱壳
0x02:简单逆向
直接跳到main
有个跳转好奇怪诶,字符串长度为0直接过?
看个伪码
- extern unsigned int g_405200[4];
- extern unsigned int g_408020;
- int sub_401594(unsigned int v5, unsigned int a0)
- {
- char v0; // [bp-0x29]
- void* v1; // [bp-0x28]
- unsigned int v2; // [bp-0x24]
- unsigned int v3; // [bp-0x18]
- void* v4; // [bp-0x14]
- sub_401c60();
- gets(&g_408020);
- v3 = strlen(&g_408020);
- for (v4 = 0; v4 < v3; v4 += 1)
- {
- v1 = v4;
- v2 = v1 >> 31;
- v0 = *((char *)(v4 + &g_408020));
- if (!sub_401504(sub_401564(sub_401410(v0, v0 >> 31, *((int *)(0x4 * v4 + (char *)&g_405200[0])), *((int *)(0x4 * v4 + (char *)&g_405200[0])) >> 31), v0 >> 31, v1, v2), v0 >> 31, v4, v4 >> 31) && !v0 >> 31)
- {
- printf("Worry!");
- exit(0); /* do not return */
- }
- }
- printf("Congratulations!");
- return 0;
- }
复制代码 很明显了 逐字节比较,且没有比较字符串长度之类的,这导致了bug2
所以,我们有如下代码
- import os,time,subprocess
- flag='SICTF{ ' # 保留空格占位
- alpha='1234567890-=~!@#$%^*_+qwertyuiopQWERTYUIOPasdfghjklASDFGHJKL:zxcvbnm,./ZXCVBNM?'
- while 1:
- for i in alpha:
- _flag=list(flag) # 转为list修改最后一位
- _flag[-1]=i
- flag=''.join(_flag)
- print('\r'+flag, end='') # 打印正在破解的flag(多酷啊)
- with open('tmp.sh','w+') as f: # 最开始的版本有bug,现在似乎没必要了
- f.write(" echo "+flag+" | babyUPX.exe")
- f=os.popen("sh tmp.sh")
- time.sleep(0.001) #给点反应时间
- ret=f.read()
- if 'Cong' in ret:
- break # 这一字节破解成功
- f.close()
- flag=flag+' ' # 保留空格占位
复制代码 0x03:结语
以后遇到类似的逐字节比较的题但又没有bug,能不能通过一些patch逐字节爆破呢?
|