首页
论坛
课程
招聘
[原创]看雪ctf秋季赛 第二题
2017-10-29 20:50 1818

[原创]看雪ctf秋季赛 第二题

2017-10-29 20:50
1818
历来第二题都比较坑,这次也比例外。
IDA打开程序,一看main函数:
.text:00401000 ; int __cdecl main(int argc, const char **argv, const char **envp)
.text:00401000 _main           proc near               ; CODE XREF: start+AF↓p
.text:00401000
.text:00401000 argc            = dword ptr  4
.text:00401000 argv            = dword ptr  8
.text:00401000 envp            = dword ptr  0Ch
.text:00401000
.text:00401000                 push    offset aCrackmeForCtf2 ; "\n Crackme for CTF2017 @Pediy.\n"
.text:00401005                 call    printf_413D42
.text:0040100A                 add     esp, 4
.text:0040100D                 mov     dword_41B034, 2
.text:00401017                 call    input_401050
.text:0040101C                 call    sub_401090
.text:00401021                 call    sub_4010E0
.text:00401026                 mov     eax, dword_41B034
.text:0040102B                 test    eax, eax
.text:0040102D                 jnz     short loc_40103F
.text:0040102F                 push    offset aYouGetIt ; "You get it!\n"
.text:00401034                 call    printf_413D42
.text:00401039                 add     esp, 4
.text:0040103C                 xor     eax, eax
.text:0040103E                 retn
.text:0040103F ; ---------------------------------------------------------------------------
.text:0040103F
.text:0040103F loc_40103F:                             ; CODE XREF: _main+2D↑j
.text:0040103F                 push    offset aBadRegisterCod ; "Bad register-code, keep trying.\n"
.text:00401044                 call    printf_413D42
.text:00401049                 add     esp, 4
.text:0040104C                 xor     eax, eax
.text:0040104E                 retn
.text:0040104E _main           endp
这么直接了当,以后有戏。判断成功的条件是
dword_41B034==0
而正好接着的两个函数就是操作这个全局变量的。
void sub_401090()
{
  int v0; // [esp+4h] [ebp-8h]
  int v1; // [esp+8h] [ebp-4h]

  if ( v1 && v0 && v1 != v0 && 5 * (v1 - v0) + v1 == 0x8F503A42 && 13 * (v1 - v0) + v0 == 0xEF503A42 )
    --dword_41B034;
}
void sub_4010E0()
{
  int v0; // [esp+4h] [ebp-8h]
  int v1; // [esp+8h] [ebp-4h]

  if ( v1 && v0 && v1 != v0 && 17 * (v1 - v0) + v1 == 0xF3A94883 && 7 * (v1 - v0) + v0 == 0x33A94883 )
    --dword_41B034;
}
按照这个构造方程,在线云算子 接了一下:
5*(v1-v0)+v1=0x8f503a42
13 * (v1 - v0) + v0 == 0xEF503A42
17 * (v1 - v0) + v1 == 0xF3A94883
7 * (v1 - v0) + v0 == 0x33A94883

化简:
6v1-5v0=0x8f503a42
13v1-12v0=0xEF503A42
18v1-17v0=0xF3A94883
7v1-6v0= 0x33A94883

系数矩阵A:
第1列   	第2列   
6.0000   	5.0000   
13.0000   	12.0000   
右边向量b:
2404399682.0000
4015012418.0000
您所输入问题的解如下:
x1	=	1253962013.4286
x2	=	-1023874479.7143
系数矩阵A:
第1列   	第2列   
18.0000   	17.0000   
7.0000   	6.0000   
右边向量b:
4087957635.0000
866732163.0000
您所输入问题的解如下:

x1	=	-890299912.6364
x2	=	1183138591.9091

根本不同解。
之后也没仔细看,试试爆破直接把堆栈的返回地址改掉可以成功,以为是溢出题。要用rop链来搞,似乎不怎么好构造完全是字母数字的shellcode。
又看了一遍题目,考虑到是乘法,且只有32位感觉有溢出。就写了爆破程序,八个字节爆破。
加上之后有事,就放那让他跑了。。。。。。。。。。。。。。。
结果。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

再站,用IDA仔细的翻了翻代码,发现了异常点:

其他的代码基本上都能反编译,而这里确全是乱码。再想到之前的溢出点,原来坑在这:
//运行到scanf时的栈情况:
0012FF6C   0041B08C  ASCII "%s"    栈顶 参数1
0012FF70   0012FF74                参数2
0012FF74   0012B870                输入的值先写入这里,从这里往下(0012FF74++ )
0012FF78   7FFD3000
0012FF7C   0040100A  
0012FF80   0040101C  返回到 ctf2017_.0040101C 来自 ctf2017_.00401050     函数返回值
0012FF84   00413E3E  返回到 ctf2017_.<ModuleEntryPoint>+0B4 来自 ctf2017_.00401000

只要超过12个字节,即可覆盖返回地址。
0x413131  转成字符是A11  反过来是11A
使用假吗1234567890ab11A 做注册码。成功进入 0x413131。
简单的单步走了几次,全是乱跳。

在0040102D |. /75 10 JNZ SHORT ctf2017_.0040103F 下断点,然后开启run跟踪:


看这个代码就清楚很多。
第一次跟踪的内容:
1234567890ab

ecx=34333231   1234
ebx=38373635   5678
edx=62613039   90ab

((ecx-ebx)<<2)+ecx+edx-0xeaf917e2==0


后边程序退出。
第一次关键跳转在:

413420 第一个关键跳 下断点。

断下来之后,改到跳转,再次run跟踪:


    ”1234“  ‘5678’
ebx=((eax + ecx)-   ebx)
eax=ebx<<1
eax=eax+ebx
eax=eax+ecx
ecx=eax
eax=eax+edx
eax-0xe8f508c8


0x41362e 跳向失败

记录如上,但是这样有个问题。 第二次记录的eax初始值不知道。

第三次尝试。
1.在retn下断点:
00401077  |.  E8 F72C0100   CALL    ctf2017_.00413D73
0040107C  |.  8D4424 08     LEA     EAX, DWORD PTR SS:[ESP+0x8]
00401080  |.  83C4 14       ADD     ESP, 0x14
00401083  \.  C3            RETN
2.在两个关键跳 413420  0x41362e 下断点。
3.在出错的地方下断点:
0040103F  |> \68 38B04100   PUSH    ctf2017_.0041B038                ;  ASCII "Bad register-code, keep trying.\n"
00401044  |.  E8 F92C0100   CALL    ctf2017_.00413D42
00401049  |.  83C4 04       ADD     ESP, 0x4
0040104C  |.  33C0          XOR     EAX, EAX
0040104E  \.  C3            RETN

执行到
00401083 
打开run跟踪,停在两个关键跳 413420  0x41362e 时修改流程,这样等程序停在出错的地方时,run跟踪就是完整的验证流程。
看着run跟踪记录如下:
前四位设为x 中间四位y  后四位 z
eax=x
ecx=eax
eax=y
ebx=eax
eax=z
edx=eax

eax=ecx=x
eax=eax-ebx=x-y

eax=eax<<2
eax=eax+ecx=eax+x
eax=eax+edx=eax+z
eax-0xeaf917e2=0

整理得到(x-y)*4+x+z=0xeaf917e2

上边正常流程之后eax==0

eax=eax+ecx=0+x
eax=eax-ebx=x-y
ebx=eax
eax=eax<<1  =(x-y)*2
eax=eax+ebx=(x-y)*2+(x-y)=(x-y)*3

eax=eax+ecx=(x-y)*3+x

ecx=eax
eax=eax+edx=(x-y)*3+x+z


eax-0xe8f508c8=0

整理之后
(x-y)*3+x+z=0xe8f508c8



eax=ecx=(x-y)*3+x
eax=eax-edx=(x-y)*3+x-z-0xc0a3c68=0



整理三个等式:
(x-y)*4+x+z=0xeaf917e2
(x-y)*3+x+z=0xe8f508c8
(x-y)*3+x-z-0xc0a3c68=0


化简
5x-4y+z=0xeaf917e2
4x-3y+z=0xe8f508c8
4x-3y-z=0xc0a3c68
http://www.yunsuanzi.com/cgi-bin/linear_system.py

您输入的问题如下:

系数矩阵A:

第1列   	第2列   	第3列   
5.0000   	-4.0000   	1.0000   
4.0000   	-3.0000   	1.0000   
4.0000   	-3.0000   	-1.0000   

右边向量b:

3942193122.0000
3908372680.0000
201997416.0000
您所输入问题的解如下:

x1	=	1953723722.0000  ==7473754A   Just
x2	=	1919903280.0000  ==726F6630   0for
x3	=	1853187632.0000  ==6E756630   0fun

注册码:Jsut0for0fun11A



[培训]12月3日2020京麒网络安全大会《物联网安全攻防实战》训练营,正在火热报名中!地点:北京 · 新云南皇冠假日酒店

收藏
点赞0
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回