pwnable.kr alloca -经验总结

本题思路:
按常规方法想在main函数中溢出时不可能的,alloca分配的空间比能输入的字符大小size一直都要大(一开始我还以为size会有个值能大过alloca函数分配的栈空间,搞了半小时后发现我真是傻的不行),那么就无法从size入手
程序中自带callme中可以getshell的函数,所以我们要控制程序的返回地址到这个函数中
g_canary 模拟栈保护机制中的canary, 在分配的栈空间后设置伪canary
*(_DWORD )&buffer[size] = g_canary;
size为正数的情况不可行,那么考虑size为负数的情况,g_canary是我们所能控制的,那么如果能把g_canary写到main函数的ret的地址上就能getshell
接下来寻找有什么地方把g_canary的值写到了栈上
在这里插入图片描述
发现在check_canary 的栈帧中发现了这个操作,那么接下来就要考虑如何控制main的返回值
再观察mani的返回地址发现是存放在ebp+var_4也就是 ebp - 4
在这里插入图片描述
那么接下来就是考虑怎么使
check_canary 中的 ebp(csheck_canary) + var_14(-14h) = ebp(main) - 4
在这里插入图片描述
观察整个流程记录ebp,esp的变化,得到一系列等式:
首先假设
main中的ebp, esp -> ebp_m esp_m
check_canary 的ebp, esp -> ebp_c esp_c
在调用check_canary 函数之前
先调用了alloca函数,
esp_m -= 16( (size + 34)/0x10 )

->sub esp , 0xc
esp_m -= 0xc
-> push eax
esp_m -= 4
->call check_canary(push eip)
esp_m -= 4
进入check_canary 后
-> push ebp
esp_m -= 4
-> mov ebp, esp
ebp_c = esp_m

最后把上面的等式都组合起来
计算ebp_c - 0x14 = ebp_m - 4
得到
esp_m - 16( (size + 34)/0x10 ) - 0xc - 4 - 4 - 4 - 0x14= ebp_m - 4*
esp_m = ebp_m - 8
忽略对齐的话算出来的size大小就是 -82
由于对齐的缘故,只要16*((size + 34)/0x10) ) 的值为**-3**,size的值不为**-82也行
接下来把
g_canary** 设置为一个栈的合法地址范围的值就行了
控制了程序的跳转地址之后,由于栈上的地址使随机的,所以把callme函数的地址大量复制到环境变量中,这样多尝试几次就能getshell

写Exp中遇到的问题:

1. 利用pwntools中的函数进行交互的时候使用
p.recvuntil("(byte) : ") 函数 交互过程会被卡住,调试的过程中发现直到执行scanf语句之前printf语句的字符串不会输出, 在执行scanf语句时前面的printf语句的字符串的内容输了出来,不知道解决办法,后来干脆不用recv之类的方法,直接sleep(1) 然后直接发送就行了

2. IDA对alloca 函数的反汇编 有点奇怪
反汇编结果:
在这里插入图片描述
源代码:
在这里插入图片描述
在调试的时候发现即使 size 的值为0,alloca函数还是会分配0x20 个字节的栈空间,原因是反汇编代码中有个固定的值3434/16 * 16的结果一直是2,也就会固定最低分配0x20 栈空间
v3 = alloca(16 * ((size + 34) / 0x10u));
这条语句的作用主要分配栈空间以及对齐

IDA中反汇编结果中的v3retaddr 是源代码中没有的,自己写了个有alloca函数的程序测试了一下,发现 反汇编出来的结果 也有void v3,而且分配的栈空间的起始地址都是赋给v3*的

3. fets函数
fgets函数的size参数为负数时不会读取任何字符,已写程序测试过

4. python中的列表解析:
*e = {str(i): 'a’10 for i in range(10)}

输出结果为:
{‘1’: ‘aaaaaaaaaa’, ‘0’: ‘aaaaaaaaaa’, ‘3’: ‘aaaaaaaaaa’, ‘2’: ‘aaaaaaaaaa’, ‘5’: ‘aaaaaaaaaa’, ‘4’: ‘aaaaaaaaaa’, ‘7’: ‘aaaaaaaaaa’, ‘6’: ‘aaaaaaaaaa’, ‘9’: ‘aaaaaaaaaa’, ‘8’: ‘aaaaaaaaaa’}
for语句前的为表达式,range()的参数使重复这个表达式的次数

5. 在设置g_canary 的值的时候 由于栈的地址是无符号类型的,直接转化为无符号数太大了,可以发送栈地址的负数形式过去比如:

/*选取的栈地址为
0xff8ae044
*/
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[]){
        int a = -7675836;
        printf("%d\n", a);
        printf("%u\n", a);
        printf("%p\n", a);
        return 0;
}

输出为:
-7675836
4287291460
0xff8ae044

原因是一个数可以被当作是正数也可以被当作是负数,取决于定义的类型,不过不管以什么形式输出,二进制码都是一样的

6. pwntools函数中process函数可以设置环境变量
比如本题中的
p = process("./alloca", env = e)

参考的writeup

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值