CTF-REV-ZERO_TO_ONE
GLIMPSE
DAY-7
QUESTION-1 insanity
- 解题思路:
- 拖到 IDA 中,\(Shift+F12\) 查看字串,直接得到 \(flag\)
- 拖到 IDA 中,\(Shift+F12\) 查看字串,直接得到 \(flag\)
QUESTION-2 open-source
- 解题思路:
- 得到了 .c 的源码,可以直接打开分析,也可以运行得到 .exe 文件后拖进 IDA 里
- 拖进 IDA 中,\(Shift+F12\) 查看字串,发现字符串 \(Get\space your\space key:\)
- 双击,\(Ctrl+x\) 交叉引用,\(F5\) 查看反编译代码。
- 发现最后输出的 \(key\) 在 \(v4\) 里最后 \(16进制\)输出:
- 看如何求 \(v4\) 的,表达式中 \(v5\) 取 \(25,25+17k\) 均可以满足条件,再把
h4cky0u
带入求得。 - 这里我使用 python 写的代码,其他语言均可:
- 运行得到 \(flag\)(不包括 \(0x\) ):
QUESTION-3 Reversing-x64Elf-100
-
解题思路:
-
拖进 IDA,\(Shift+F12\) 查看字符串,发现关键字符串
Nice!
-
双击,\(Ctrl+x\) 交叉引用,\(F5\) 查看反编译代码。
-
发现整个程序很简单仅有一个判断,\(sub_4006FD\) 函数不匹配则密码正确。
-
注意这里
(__int64)
是将输入的 \(字符串数组s\) 作为一个 \(64位整数\) 传参,本质都是二进制数据。
-
进入函数内发现存储方式也是如此,一个
__int64
可以简单看作char[16]
,
-
那么访问方式
*(char *)(v3[i%3] + 2*(i/3))
可以看作v3[i%3][2*(i/3)]
-
这里的 \(al\) 也就是最后的答案也是如此,相当于存入 \(char[16]\) 中,
-
简单输出遍历的字符:
- 然后写出操作代码,得到 \(flag\) :
-
QUESTION-4 re1
-
解题思路:
- 拖进 IDA,\(Shift+F12\) 查看字符串,发现关键字符串 \(flag\space get\)
- 双击,\(Ctrl+x\) 交叉引用,\(F5\) 查看反编译代码。
- 发现 \(v3\) 为 \(0\) 时输出
aFlagGet
,非 \(0\) 时输出aFlag
- 查看字符串内容
aFlagGet
为flag get
,aFlag
下方的数据未识别,\(Alt+A\) 选择 \(CP936\) 查看下发现
-
与程序输出相同,可以确定是上方 \(strcmp\) 匹配成功时密码正确
-
那么查看 \(v5\) 的具体内容,双击发现一串问号,看到
xmmword
可以返回了,应该和它有关:
-
返回找到上方的 \(v5\) 赋值,找到
xmmword
的具体值:
-
这是一串 \(16进制\),但之后进行的是字符串匹配操作,转成字符串查看,直接找个在线网站:
-
感觉有点像,又带括号,仔细看题目名称中提到的 \(DUTCTF\),正是这个字符串反过来的前几个字母,写个翻转:
-
好像缺了一半,再去代码里仔细找找,发现第一句 \(printf\) 好像后面还干了些什么:
-
\(右键,同步到,IDA View-A\),查看汇编代码,发现中间有一些初始化操作:
-
可以发现,\(v5\) 的初始化分为两个部分,前面的
xmmword
已经求得,再看后面的qword
:
-
再次转成字符串,发现也是倒过来的字符串。
-
其实这是因为存储数据时将字符串低位放在存储单元的低位,读出来的时候就倒序了。
-
反过来,再与之前的字符串拼起来,得到 \(flag\)
DAY-8
QUESTION-5 simple-unpack
- 解题思路:
-
日常先查壳(之前的题目没写出来),拖进 \(exeinfo\) ,发现是 \(upx\) 加壳:
-
cmd 打开 upx 脱壳,轻松脱掉:
-
拖进 IDA,发现有 \(main\) 函数,\(点开+F5\):
-
功能看起来很简单,\(strcmp\) 与名为 \(flag\) 的变量比较,点开查看一下,直接得到 \(flag\):
-
QUESTION-6 logmein
-
解题思路:
-
日常查壳,发现 gcc 编译没壳
-
拖进 IDA,\(Shift+F12\) 发现关键字符串
Incorrect password!\n
:
-
双击,\(Ctrl+x\) 交叉引用,\(F5\) 查看反编译代码。
-
发现只是一个子函数,返回去找输入提示
Enter your guess:
,双击 \(Ctrl+x+F5\):
-
发现对输入字符串的长度有要求,要大于字符串 \(v8\) 的长度,\(flag\) 由最后的
if
内的操作得到: -
带入 \(v6=7\) 发现
i%7-8
一定是负数,考虑到内存访问本质是指针偏移,查看 \(v8\) 之前的变量:
-
所以
(char)v8[i\%7-8]
本质是在访问 \(v7\) 内的字符串,将其16进制转字符串:
-
发现刚好 \(7位\),所以原来的
(char)v8[i%7-8]
等同于v7[i%7]
,则可以写出操作脚本复现: -
需要注意的是 \(v8\) 的赋值中有
\%
这是一个转义字符,所以 \(v8\) 的长度为 \(17\): -
前面的题目讲到,字符串存储方式是低位地址存低位,读出来的 \(v7\) 是倒序的,记得翻转一下:
-
最后得到 \(flag\):
-
QUESTION-7 game
-
解题思路:
-
日常查壳,拖进IDA,\(Shift+F12\),找到关键字符串
done!!! the flag is
:
-
双击,\(Ctrl+x\) 交叉引用,\(F5\) 反编译,
-
发现里面为 \(v2,v3,v4,v5\) 赋了一系列初值:
-
往下看发现将 \(v2\) 与 \(v5\) 的每个字符一一异或,再异或个常数就得到 \(flag\):
-
但是 \(v2\) 长度没有 \(56\),看上方数据的定义顺序,本质是把 \(v2,v3,v4\) 拼一起与 \(v5\) 操作:
-
写出操作脚本复现:
-
最后输出得到 \(flag\):
-
QUESTION-8 Hello, CTF
- 解题思路:
-
日常查壳,拖进IDA,\(Shift+F12\),找到关键字符串
success!
: -
双击,\(Ctrl+x\) 交叉引用,\(F5\) 反编译,发现当 \(v10,v13\) 相同时输出:
-
\(v10\) 是输入的字符串转 \(16进制\) 后的结果,\(v13\) 则也是某个字符串转 \(16进制\)
-
在线转一下得到 \(flag\):
-
QUESTION-9 getit
- 解题思路:
-
日常查壳,拖进IDA,\(Shift+F12\),找到关键字符串
harifCTF{???}
: -
双击直接 \(Crtl+x\) 发现没有交叉引用,仔细看发现该变量 \(t\) 从上方就开始定义了:
-
所以其实最前面还有一个 \(53h\) 即 \(S\),先不急,
-
光标点击 \(t\) 所在的行,\(Ctrl+x,F5\) 查看反编译代码:
-
简单分析,将串 \(s\) 里 \(偶数位-1,奇数位+1\) 存到串 \(t\) 的中间,然后将 \(t\) 输出到一个 \(flag.txt\) 的 \(linux\) 下的临时文件里,
-
联想到 \(t\) 内先前的抬头 \(SharifCTF\) ,猜测 \(t\) 即最后的 \(flag\),
-
查看 \(s和t\) 内的值,然后写出操作脚本复现:
-
最后得到 \(flag\):
-
如果是在 \(linux\) 下运行,可以通过动态调试打上断点,然后直接打开 \(txt\) 文档查看 \(flag\)
-