前提:linux系统(我是用ubuntu),并装有pwntools,python
0x1 easy pwn
为了方便大家理解,附上程序的源代码
1 | #include<stdio.h> |
我们将程序导入IDA中,注意该程序是64位程序,所以需要导入到x64的IDA中
然后F5反编译为伪代码
很明显这是一个read溢出漏洞,我们只需要在输入buf时,多输入一些数据,使得输入的数据将v5覆盖,我们先双击buf看看栈的情况
但是我们不知道v5在栈中位置,返回到伪代码,然后双击v5
发现指向var_4,所以v5=var_4
buf开始读入数据一直到var_4,中间需要读入0xC-0x4=0x8,所以我们要先输入8个垃圾数据,然后紧跟着2019即可,例如: aaaaaaaa + (2019) 这样就可以将var_4的数据覆盖成2019
附上我的payload
1 | from pwn import * |
执行代码
得到flag: xgctf{Chan9e_th4_sTaCk!}
0x2
为了方便大家理解,附上程序的源代码
1 | #include<stdio.h> |
简单说明一下思路:首先main里面直接调用vul_function,然后再vul_function中直接返回read且读入数据的长度大于junk字符串长度,存在溢出
栈的结构 junk+ebp+ret_address+pading +参数1+参数2 +…… +参数n
所以我们输入的字符首先先填满junk,然后再覆盖ebp,然后覆盖ret_address为getShell的地址,然后vul_function执行完返回时 直接返回到getShell,拿到shell
接下来我们开始分析文件,将文件导入IDA中,F5反编译
然后进入vul_function
双击头部的 char buf; // [esp+8h] [ebp-10h] 的buf
根据[ebp-10h] 我们知道junk首先需要覆盖 0x10 的长度
接下来要覆盖ebp,32位程序中ebp为四个字节,所以可以随意用4个字节的数据填充掉,然后就是ret_address(返回地址)
我们需要找到能让我们拿到shell的函数,我们双击进入
显然只要我们执行了 system("/bin/sh") 就可以拿到flag
接下来我们开始构造payload,我使用的是python
1 | from pwn import * |
执行结果如下
得到flag: xgctf{r4tn_t0_get5hell}
0x3 反向读取
这道题考察了对于数组下标为负的溢出
题目告诉我们,只要在本地输出 FAKE{************} 然后调整为远程连接 即可得到flag
首先我们先把程序拖入IDA中,注意了该程序为x64程序,所以需要x64的IDA
然后F5进行反编译
双击vul_function
我们在以下这条语句中发现了漏洞
1 | if ( *((_BYTE *)&v2 + i) != *((_BYTE *)&v8 + s[i]) ) |
&v8是地址,若s[i]为负数的话,就可以读到低位的数据,那么这个表达式就等效于
if ( *((_BYTE *)&v2 + i) != *((_BYTE *)&v2 + i) ) 显然这个if结果是false,就可以执行printf("%s",&v2); 得到flag了
对此我们需要验证我们输入的数据,是否在转化为char的时候存在负数,注意了数组s是char,不是int
我编写了以下的C++代码来验证
1 | #include<iostream> |
执行结果如下
由于char的范围是1-127,溢出后就会变成负数,即 128 之后为负数
那么我们就可以通过该特点来溢出低位数据
双击 v2 ,查看它在栈中的位置,v2 = var_80
返回伪代码,双击v8查看它在栈中的位置,v8 = var_40
那么我们来总结一下思路,首先我们要先想办法输入溢出的char,然后让它偏移到和自身相等的位置去,就可以跳过 结束的if
偏移量应该是 v8 - v2 = 0x40
然后我们确认 哪个溢出的char是 0x40,通过上面的C++程序,我们知道了十进制的192溢出后等于-64,即-0x40
接下来我们开始写payload,这里我是用python写的
1 | from pwn import * |
执行结果如下
得到flag: xgctf{1eak_Char_t0_g4t_F1ag}
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 咲夜南梦's 博客!
评论