【WP】攻防世界之pwn200
简单的栈溢出,学习一下使用pwntools中的DynELF模块
DynELF由于 ASLR 的影响,我们在获取某些函数地址的时候,需要一些特殊的操作。一种方法是先泄露出 libc.so 中的某个函数,然后根据函数之间的偏移,计算得到我们需要的函数地址,这种方法的局限性在于我们需要能找到和目标服务器上一样的 libc.so,而有些特殊情况下往往并不能找到。而另一种方法,利用如 pwntools 的 DynELF 模块,对内存进行搜索,直接得到我们需要的函数地址
为了使用 DynELF,首先需要有一个 leak(address) 函数,通过这一函数可以获取到某个地址上最少 1 byte 的数据,然后将这个函数作为参数调用 d = DynELF(leak, main),该模块就初始化完成了,然后就可以使用它提供的函数进行内存搜索,得到我们需要的函数地址。
类 DynELF 的初始化方法如下:def __init__(self, leak, pointer=None, elf=None, libcdb=True):
参数
意义
leak
leak 函数,它是一个 pwnlib. ...
【WP】简单的srop
一道简单应用srop的题目
题目描述程序调用一个存在漏洞的函数直接看汇编,64位函数调用前三个参数依次使用rdi,rsi,rdx寄存器传参,对于这里的read函数,第二个参数即读入内容存储地址,由于这里mov rsi, rbp,所以直接把输入内容写入rbp,执行完read函数后将rbp的值赋给rsp,然后执行retn指令,而retn指令只管读出栈顶的值作为返回地址,所以如果我们直接输入一个地址,就会返回到我们输入的地址处
同时发现程序内存在一处没有调用到的函数,有一个mov eax, 0Fh指令,而sigreturn的系统用调用号就是0xf,所以可以利用这里达到利用srop的目的
同时程序中存在/bin/sh,可作为system的参数调用从而getshell
exp123456789101112131415161718192021from pwn import*context(os='linux', arch='amd64', log_level='debug')r = process('./sro ...
【WP】orw的shellcode编写
本题来自HGAME2021 week1
题目描述存在负数溢出LOWORD 取第十六位
读十字节数据到栈上,通过atoi函数将读入数据转换为int类型数据并赋给变量length,而length为unsigned int且位于bss段
将unsignde int的变量强制转换为signed int类型并与15比大小,只需要写入负数即可绕过比较同时触发栈溢出
程序存在seccomp,无法调用system等系统调用函数,open,read,write函数可用,考虑通过这三个函数读取并显示flag文件
程序存在rwx段,且NX保护未开启,于是可以通过在栈上写入shellcode并执行
exp1以jmp rsp指令为跳板思路:输入一个负数,经atoi函数转化后存在buf里,然后取它的低双字部分(对应后面的8个16进制数),使它是 jmp rsp对应的地址。第二次输入时返回地址布置为jmp rsp,紧接着填充orw的shellcode
如何寻找jmp rsp地址呢?写一段shellcode然后查看1234shellcode = 'jmp rsp'res = asm(shell ...
Python异常处理
两个非常重要的功能python提供了来处理两个非常重要的功能python程序运行中出现的异常和错误
异常处理
断言 assertions
| BaseException | 所有异常的基类 || —— | —— || SystemExit | 解释器请求退出 ||KeyboardInterrupt | 用户中断执行(通常是输入^C)||Exception | 常规错误的基类||StopIteration | 迭代器没有更多的值||GeneratorExit | 生成器(generator)发生异常来通知退出||StandardError | 所有的内建标准异常的基类||ArithmeticError | 所有数值计算错误的基类||FloatingPointError | 浮点计算错误||OverflowError | 数值运算超出最大限制||ZeroDivisionError | 除(或取模) ...
【WP】adworld之pwn进阶区stack2
题目描述执行程序后提示可以输入0~255大小的数字先问要输入几个数字然后输入相应个数的数字后跳出菜单可以显示输入的数字,添加数字,改变数字,获得均值和退出
发现漏洞存在于更改数字时没有检查是否越界,于是可以修改栈上的数据
存在后门函数
所以可以通过再修改数字时把返回地址修改为后门函数的地址
本题的几个注意点:
利用后门的方式在本地可以打通,但远程打不通(远程没有bash。实际上system(‘sh’)也可以getshell,通过布置system的plt表地址为返回地址的位置,’sh‘的地址为参数的位置即可
由于该程序为LSB小端序,低位字节存入低地址,高位字节存入高地址,所以在修改地址时我们需要从低地址到高地址由后往前书写12345678h在小端序中存放结果如图
IDA分析出来的偏移量不正确,需要gdb调试得出结论,这里重点记录一下在一开始输入两个数255和254(0xff,0xfe)【这里输入两个数是因为发现如果只输入一个数,最后栈里会存在两个相同的数无法判断哪一个是我们想要的】在程序最后还没有开始退栈时下一个断点(局部变量还在)在程序退栈到ret指令时下一个断点,此时栈顶指向 ...
【WP】adworld之pwn进阶区Mary_Morton
题目描述查看保护12345678pwndbg> checksec[*] '/home/ayoung/Desktop/temp/temp/adworld/Mary_Morton' Arch: amd64-64-little RELRO: Partial RELRO Stack: Canary found NX: NX enabled PIE: No PIE (0x400000)
分析程序F5,执行后出现三个选项,选项一可以触发栈溢出漏洞,选项二可出发格式化字符串漏洞,选项三退出。注意到本题开启了canary保护,于是考虑通过格式化字符串泄露canary,然后再进行栈溢出
选项一进入的函数
选项二进入的函数
存在后门
计算参数计算得到输入位于第6个参数同时可以算出canary距离栈顶0x90-0x8=136个字节,136/8=17,所以canary的位置对应第23个参数,所以我们用”%23$p”输出canary的值。本题64位,故canary长度8字节,需要接收16个字符(16进制)。成功泄露 ...
Canary保护相关
对抗canary保护技术
泄露canary值
直接泄露栈上canary利用输出函数,不输入’\x00’,让canary的值被打印出来栈溢出时在覆盖时把canary覆盖成它本身的值
泄露fs:28内的值假设有任意读的功能的函数,则去读取fs:28h地址的值(验证值)当我们已经泄露libc基址时即可以算出该地址位置,且每次程序执行该地址与libc基址偏移固定不变(程序开始时会把fs:28的值保存在栈上作为canary,程序结束时会把canary的值和fs:28h比较,不一样则调用__stack_chk_fail,一样则正常返回)【补图】
覆写副本值如果有任意写的能力可以考虑把fs:28h的值覆写掉
劫持stack_chk_fail可以修改全局偏移表(GOT)中存储的__stack_chk_fail函数地址(如通过格式化字符串),便可以在触发canary检查失败时,跳转到指定的地址继续执行。
stack smashing
当canary被覆盖之后,会call到__stack_chk_fail打印argv[0]这个指针指向的字符串,默认argv[0]是程序的名字
如果我 ...
【WP】BUUCTF之【BlackWatch入群题】PWN
栈迁移
题目描述查看保护
IDA看代码
发现存在两处读入第一处往s处读入0x200字节(s位于bss段,可写)第二处往buf处读入0x20字节发现buf的空间为0x18,读入0x20,则存在溢出,但最多溢出0x20-0x18=8字节程序为32位,所以最多只能覆盖ebp和返回地址于是需要利用栈迁移
注意:
由于函数结束退栈时有一次leave,ret的操作,我们为了达到栈迁移的目的又进行了一次leave,ret。所以需要覆盖ebp为想覆盖的地址-4,在这里即覆盖为bss_addr-4(或者在布栈时一开始用四字节垃圾数据填充)exp12345678910111213141516171819202122232425262728293031323334from pwn import*from LibcSearcher import*context(os='linux', arch='i386', log_level='debug')#r = remote("node3.buuoj.cn", 27677)r = pr ...
SROP
Sigreturn Oriented Programming这里的sigreturn是一个系统调用,在unix系统发生signal的时候会被间接地调用
signal机制signal机制是类unix系统中进程之间相互传递信息的一种方法,一般称为软中断信号或软中断比如进程之间可以通过系统调用kill来发送给软中断信号信号机制常见步骤如下图
(进内核保存,出内核恢复)
SROP原理内核会为该进程保存相应的上下文,主要是将所有寄存器压入栈中,以及压入signal信息,以及指向sigreturn的系统调用地址称ucontext及siginfo这一段为Signal Frame。注意,这一部分是在用户进程的地址空间的。之后会跳转到注册过的signal handler中处理相应的signal。因此当signal handler执行完之后,就会执行sigreturn代码
此时栈结构如下图所示
原来的栈下面的ucontext和siginfo、sigreturn的信息拼起来如下图(可以看到在栈里保存了各种寄存器的值等信息)
内核工作:为进程保存上下文并恢复上下文,变动在Signal Frame里注意:
S ...
栈迁移
利用情况
未开启NX保护
栈溢出空间较小,无法直接泄露libc_base
以32位为例使用call命令,进入一个函数时,程序会进行一系列栈操作:123push eip+4push ebpmov ebp,esp用来保护现场,避免执行完函数后堆栈不平衡以及找不到之前的入口地址
leave ret相当于1234leave ==> mov esp, ebp pop ebpret ==> pop eip逆着看上面这段指令pop eip是弹出栈顶数据并存入eip寄存器而栈顶数据是由esp的值决定的又由于mov esp, ebp是把ebp的值赋给esp我们知道eip控制cpu下一条指令所以我们可以通过覆盖ebp的值来控制ret返回地址
而两次leave ret即可控制esp为我们想要的地址由于有pop ebp会使esp-4,所以将ebp覆盖为想要调整的位置-4即可








