这段时间作业有些多,所以writeup
写的有些晚了。这是一道没有反调试、没有加壳的题,用ida的F5大法
直接就可以看到“源码”和两个“校验方程的函数”让第一次做CTF题的我认为这就是让我解方程啊!于是就写程序穷举方程了,结果被套路了一天。。。
在穷举半天没有结果之后就感觉被套路了,于是仔细分析
如果解题方法真的是溢出的话,溢出覆盖的地址肯定是比赛规则中的可输入字符。
首先猜想溢出后的地址的代码会jmp
到0x0040102F
这个地址,于是全局搜索0x0040102F
,没有匹配到。
于是手动在ida中查看符合要求的地址,于是发现了下面的符合要求数据:
这一堆数据比较蹊跷,仔细观察里面出现了很多0x75、0x71
等含有7
的数据,然后再猜想不是直接jmp
到固定地址,应该是相对跳,对应intel
手册中jxx
查的跳转指令的二进制代码(因为作者不一定要用jmp
):
此时我还天真的以为这段数据里面有一个指令会跳转到0x0040102F
那里,幸好一个机灵反应到目前除了覆盖返回地址的那几个字符有用其他字符都是没用的,如果真是这样的话这道题就多解了,所以立马想到应该还有验证前面几个字符的代码要执行,所以这堆数据应该是真正的校验代码!
这段数据/代码的首地址是0x00413131
,刚好是ASCII码的11A
,先输入12345678901211A
溢出到目标地址:
首先F9
跑起来看看发生了什么:
然后我使用了od的指令跟踪功能,在'0x40103F'的位置(提示验证失败的代码)下断点,重新调试断到0x00413131
的位置,打开od->查看->run跟踪
窗口,然后点击od->调试->跟踪步入
,来看看结果(后来才了解到有去花指令的插件),所有执行过的代码都记录在了Run trace
窗口中:
同时也发现了里面有很多无用的跳转,看来作者也是通过这些跳转来使得这部分指令不能被ida和od识别
但是因为是验证失败了,所以肯定有部分指令没有被执行,所以有部分没有记录下来。这时上网搜了去花指令插件的使用方法,才发现花指令这么好去
本来懒得手动还原,准备使用RadAsm编译后用ida辅助还原,结果一值搞不对,后来就手动还原公式了
这次Fpc大佬的出题给我这样的新人上了很好的一堂课,感谢Fpc、感谢看雪
lea eax, [esp+0Ch+var_C]
push eax
push "%s"
call _scanf
.386
.model flat, stdcall ;32 bit memory model
option casemap :none ;case sensitive
includelib TestRad.Inc
.const
.data?
; 构造条件开始
g_input dd 0
g_EAF917E2 dd EAF917E2h
g_E8F508C8 dd E8F508C8h
; 构造条件结束
.code
CheckFun proc C
; 构造条件开始
mov eax, 11Ah
push eax
mov eax, 3333h
push eax
mov eax, 2222h
push eax
mov eax, 1111h
push eax
; 构造条件结束
xor eax, eax
mov dword ptr [g_input], eax
pop eax
mov ecx, eax
pop eax
mov ebx, eax
pop eax
mov edx, eax
mov eax, ecx
sub eax, ebx
shl eax, 2
add eax, ecx
add eax, edx
sub eax, dword ptr [g_EAF917E2]
je TWO
ret
TWO:
add eax, ecx
sub eax, ebx
mov ebx, eax
shl eax, 1
add eax, ebx
add eax, ecx
mov ecx,eax
add eax, edx
sub eax, dword ptr [g_E8F508C8]
je THREE
ret
THREE:
mov eax, ecx
sub eax, edx
ret
CheckFun endp
start:
invoke CheckFun
ret
end start
(x - y) << 2 + x + z == 0xEAF917E2
(x - y) << 1 + x - y + x + z == 0xE8F508C8
(x - y) << 1 + x - y + x - z == 0x0C0A3C68
这段时间作业有些多,所以writeup
写的有些晚了。这是一道没有反调试、没有加壳的题,用ida的F5大法
直接就可以看到“源码”和两个“校验方程的函数”让第一次做CTF题的我认为这就是让我解方程啊!于是就写程序穷举方程了,结果被套路了一天。。。
在穷举半天没有结果之后就感觉被套路了,于是仔细分析
本来懒得手动还原,准备使用RadAsm编译后用ida辅助还原,结果一值搞不对,后来就手动还原公式了
这次Fpc大佬的出题给我这样的新人上了很好的一堂课,感谢Fpc、感谢看雪
- 打开od断点下到
0x00401077 call scanf
的位置,输入123456789012
(刚好撑满12字节的临时变量空间,溢出了字符串结尾处自动补的0x00
)
- 首先观察输入前的栈环境:
- 再观察输入后的栈环境:
- 根据上图中的栈环境再结合
scanf是cdcall调用约定
发现返回地址在我们溢出一个字节0x00
后变成了入口地址,按F9
跑起来后程序又来到了要求输入的地方:
-
瞬间感觉这里就是作者给的提示!当时立马想到如果溢出到提示"You get it!"的地址就破解了此题,但是又发现这里的地址是
0x0040102F
,地址中的0x10
是无法输入的字符\^p
(但是可以粘贴进去):
- 如果真的可以溢出到该地址的话这道题又是多解了,所以答案肯定不在这里
- 首先观察输入前的栈环境:
- 再观察输入后的栈环境:
- 根据上图中的栈环境再结合
scanf是cdcall调用约定
发现返回地址在我们溢出一个字节0x00
后变成了入口地址,按F9
跑起来后程序又来到了要求输入的地方:
-
瞬间感觉这里就是作者给的提示!当时立马想到如果溢出到提示"You get it!"的地址就破解了此题,但是又发现这里的地址是
0x0040102F
,地址中的0x10
是无法输入的字符\^p
(但是可以粘贴进去):
- 如果真的可以溢出到该地址的话这道题又是多解了,所以答案肯定不在这里
-
如果解题方法真的是溢出的话,溢出覆盖的地址肯定是比赛规则中的可输入字符。
-
首先猜想溢出后的地址的代码会jmp
到0x0040102F
这个地址,于是全局搜索0x0040102F
,没有匹配到。
-
于是手动在ida中查看符合要求的地址,于是发现了下面的符合要求数据:
-
这一堆数据比较蹊跷,仔细观察里面出现了很多0x75、0x71
等含有7
的数据,然后再猜想不是直接jmp
到固定地址,应该是相对跳,对应intel
手册中jxx
查的跳转指令的二进制代码(因为作者不一定要用jmp
):
-
此时我还天真的以为这段数据里面有一个指令会跳转到0x0040102F
那里,幸好一个机灵反应到目前除了覆盖返回地址的那几个字符有用其他字符都是没用的,如果真是这样的话这道题就多解了,所以立马想到应该还有验证前面几个字符的代码要执行,所以这堆数据应该是真正的校验代码!
- 幸好我在科锐刚学习完汇编老师有讲到花指令的的相关知识,就是通过加无用的数据使得代码在静态分析和od没有走到目标代码是这些代码看起来是乱的:
-
这段数据/代码的首地址是0x00413131
,刚好是ASCII码的11A
,先输入12345678901211A
溢出到目标地址:
-
首先F9
跑起来看看发生了什么:
- 执行了验证代码!!!
-
然后我使用了od的指令跟踪功能,在'0x40103F'的位置(提示验证失败的代码)下断点,重新调试断到0x00413131
的位置,打开od->查看->run跟踪
窗口,然后点击od->调试->跟踪步入
,来看看结果(后来才了解到有去花指令的插件),所有执行过的代码都记录在了Run trace
窗口中:
-
同时也发现了里面有很多无用的跳转,看来作者也是通过这些跳转来使得这部分指令不能被ida和od识别
-
但是因为是验证失败了,所以肯定有部分指令没有被执行,所以有部分没有记录下来。这时上网搜了去花指令插件的使用方法,才发现花指令这么好去
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课