1.open-source:
此题目得到附件为C代码,方法为直接对源码进行分析;
分析可得flag分为三个字符串存放在了argv[1],argv[2],argv[3],逐个分析:
unsigned int first = atoi(argv[1]);
if (first != 0xcafe) {
printf("you are wrong, sorry.\n");
exit(2);
}
可知first=0xcafe时得到正确结果
unsigned int second = atoi(argv[2]);
if (second % 5 == 3 || second % 17 != 8) {
printf("ha, you won't get it!\n");
exit(3);
}
对if条件取反后可以得到正确的second,此处使用Python编写脚本
for second in range(0,100):
if(second%5!=3 and second%17==8):
print(second)
*注:此时输出了一个8,明显不符合,没找到问题所在
second首先取最小值25实验
if (strcmp("h4cky0u", argv[3])) {
printf("so close, dude!\n");
exit(4);
}
可知argv[3]为字符串“h4cky0u”;
unsigned int hash = first * 31337 + (second % 17) * 11 + strlen(argv[3]) - 1615810207;
对三个字符进行转换可以得到hash即为最后结果,运行c代码,查看输出hash
得到输出 c0ffee,验证后为正确结果!
2.simple-unpack:
得到附件后使用exeinfope工具查看
可见该文件为upx加壳,使用upx脱壳后(upx使用见下方介绍)再次使用exeinfope查看
可以看出脱壳后的区别,ida反汇编脱壳后的文件,可以看到与脱壳之前的反汇编相比,函数窗口函数增多,且可以发现main函数
对main函数进行反汇编,得到伪代码如下
代码逻辑结构很清晰,为比较S1与flag字符串,双击flah=g后得到
很明显单引号内字符串‘flag{Upx_1s_n0t_a_d3liv3r_c0mp4ny}’ 即为flag!
第二种方法:
在Hex -view 窗口使用快捷键 Alt+T ,搜索字符串“flag”,也可发现相同的答案,但在脱壳之前的进行搜索,得到flag含有乱码
4n后面含有符号,除脱壳外不知道还有没有其他办法解决???
*补充upx使用 *
upx是一个可执行文件压缩器,是一个控制台应用程序,以命令行方式进行操作
压缩可执行文件被称作加壳,解压可执行文件被称为脱壳
upx 1234.exe //对可执行文件123加壳
upx --best 1234.exe //以最大压缩率对1234文件加壳
upx -d 1234.exe //对1234文件脱壳
3.logmein:
找到main函数,反汇编后得到伪代码
可以看到在经过判断之后有两个函数,sub_4007c0为Incorrect password输出,sub_4007F0为You entered the correct password!输出,可见只有运行到sub_4007F0才为正确的flag。代码逻辑大致为只有s满足长度小于v8且 s[i] = (char)(*((_BYTE *)&v7 + i % v6) ^ v8[i])时才能顺利到达sub_4007F0函数处得到正确输出
编写Python脚本
#import math
v8=":\"AL_RT^L*.?+6/46"
v7="harambe" //由十六进制转换而来
v6=7
s=''
for i in range(0,len(v8)):
s += chr(ord(v8[i]) ^ ord(v7[i%v6])) //ord为转换为二进制,chr为转换为字符串
print(s)
可以得到输出即为flag
问题:v7的十六进制码使用快捷键R转换为字符是“ebmarah“。此处涉及字符存储的大端模式和小端模式。小端模式即低字节在地位地址,高字节在高位地址;大端模式为低字节在高位地址,高字节在低位地址。大端模式下读取顺序刚好相反。
但此处是如何判断是大端模式还是小端模式??
4.insanity
反汇编后查找字符串
很容易找到flag
5.python-trade:
下载后得到.pyc文件,.pyc文件是Python编译产生的中间文件,使用在线工具https://tool.lu/pyc/ 对pyc文件进行反汇编,得到代码
代码逻辑很明显是对输入的flag进行encode函数内的处理后与correct字符串进行比较,只要对encode函数进行逆向分析即可得到应该输入的内容。代码中引入了base64模块,对得到的s进行了base64编码,逆向分析是首先应该讲correct进行base64解码
import base64
s='renhongcheng'
s=base64.b64encode(s) //对s字符串进行base64编码
s=badse64.b64decode(s) //对编码后的字符串进行base64解码
编写Python脚本对代码进行逆向求解
import base64
correct='XlNkVmtUI1MgXWBZXCFeKY+AaXNt'
flag=''
correct=base64.b64decode(correct) //首先对字符串进行base64解码,得到为byte类型,存储方式为二进制,所以后续不需要进行ord
for x in correct:
x=x-16
x=x^32 // ^为异或运算符,按位异或运算
flag += chr(x)
print(flag)
得到输出
需要注意^ 异或运算符的求逆运算, a^b=c , 则 b ^c =a
6.game: //动态调试
文件为exe可执行文件,使用ida32位打开文件,找到main函数就反汇编得到伪代码
可以发现核心代码,判断数组的八个数据全为1后即可实现函数sun_457AB4的调用,进入该函数查看后可以发现,此函数即是游戏通关后输出flag的函数。此题采用动态调试,控制执行流的方法实现,改变执行流,无需判断,直接调用输出函数实现flag的输出。查看该函数的地址备用。
关于动态调试踩过的坑不再赘述,此程序选用window远程调试:
在ida安装目录下打开win32_remote.exe
ida中选择remote Windows debugger,在程序开头处F2下断点,F9运行后设置参数
程序在断点卡住,下一步只需要修改EIP的值指向flag的输出函数
修改EIP之后马上可以看到执行控制流的改变
F8步出函数后再次查看cmd对话框
可以看到flag的输出,断点之后的内容没有输出,直接跳转到了flag的输出!
补充:EIP寄存器存储着我们cpu要读取指令的地址,每次cpu执行都要先读取eip寄存器的值,然后定位eip指向的内存地址,并且读取汇编指令,最后执行
7.Hello CTF:
直接使用ida反汇编得到伪代码
代码逻辑很明显是在比较v10与v13,v13已知,此时不用分析中间v10的来源即可一直到v13的值为flag,只需要将1进制转换后就可以拿到flag(前面代买就是将输入的v9赋值给v4,v4给v8,v8给v10)