攻防世界 pwn 新手
前言
攻防世界 pwn 入门
hello pwn
64位程序 read函数读取0x10到地址601068然后与地址60106c进行比较
因为这两个地址相差4,但是可以读取10
poc:
from pwn import * |
level0
但是只发现了在函数列表中存在一个callsystem函数
那么可以先填充80个字节,然后,将rip填充为callsystem()的地址
call, 执行函数调用. 当 CPU 执行 call 指令时, 首先会把 rip 寄存器的值入栈, 然后设置 rip 值为目标地址, 由于 rip 寄存 器的值决定了下一条CPU需要执行指令的位置, 所以当 CPU 执行完成当前 call 指令后就会跳转到目标地址.
因此可以借助vulnerable_function()的read函数,将缓冲区填充满,再将ebp+0x8即eip所在的地址覆盖为callsystem函数地址
,即可得到shell。
poc:
from pwn import * |
Level2
32位程序
Read存在溢出,buf这个字符数组的长度只有0x88,却可以输入0x100的东西,能覆盖掉数组外面的东西。当属于数组的空间结束后,有一个4个字节长度的s,其次是一个存放着返回地址的r。我们可以输入数据,覆盖返回地址r。
没有什么危险,也没有像level0一样,有后门函数
在 .plt段 发现_system函数且在 数据段 发现/bin/bash地址
根据32位程序栈结构:
poc:
from pwn import * |
p32(0)是为了填充函数返回地址,随便返回到哪都行
guess_num
Gets栈溢出覆盖seed的值 使其为伪随机数
poc:
from pwn import * |
int_overflow
整数溢出
无符号整数类型的v3 存入到al 8位寄存器
可利用函数且有地址
那么整数的范围就是0-255(00000000–11111111)
如果超过这个范围那么就会进行模运算比如 输入257 那么结果就是 257%255=2
可以看到有一个前提条件就是我们输入的长度必须是,(4,8]才能进入到else 那么输入的长度就应该是(259,263]
通过strcpy来让dest溢出,覆盖返回地址到what_is_this()
那么payload = 'a'*(0x14+4)+p32(flag).decode('iso-8859-1')+'a'*232
poc:
from pwn import * |
cgpwn2
Fgets传入/bin/sh
Gets栈溢出跳到system
poc:
from pwn import * |
构造payload的时候注意这是32位程序,而32位程序调用函数时栈的结构为:调用函数地址->函数的返回地址->参数n->参数n-1->···->参数1
level3
参考:
攻防世界PWN题 level3 - 愚人呀 - 博客园 (cnblogs.com)
[原创]XCTF攻防世界 level3-Pwn-看雪论坛-安全社区|安全招聘|bbs.pediy.com
Buf定义0x88但是可以输入0x100
但是没有像上面题目存在system函数和/bin/sh的字符串,但是write函数是载入了外部的运行库
那就通过write函数打印出泄露的write函数在got中的地址 然后通过.so文件找出write在libc_32.so.6中的地址 接着就可以计算出libc基地址了。
poc:
from pwn import * |
payload1中:
b'a'*0x88+b'a'*0x4+p32(write_plt)+p32(main)+p32(1)+p32(write_got)+p32(4) |
那么为啥要传个write_got呢?
我理解是现在的write_got存放的是这个程序运行时write函数的地址
,如下图
那么正好就打印了write函数地址造成泄露,又因为库函数中字符串常量和函数之间的相对位置也是确定的
,所以可以找到当前system函数的真实地址并利用
CGfsb
参考:XCTF Pwn CGfsb | NiceSeven’s Website
格式化字符串漏洞的简单利用
printf函数的格式化字符串常见的有 %d,%f,%c,%s,%x(输出16进制数,前面没有0x),%p(输出16进制数,前面带有0x)等等
。
但是有个不常见的格式化字符串 %n
,它的功能是将%n之前打印出来的字符个数,赋值给一个变量
。
%n,不输出字符,但是把已经成功输出的字符个数写入对应的整型指针参数所指的变量。
变量pwnme
的位置在bss段,地址为0x0804a068
bss段(bss segment)通常是指用来存放程序中未初始化的全局变量的一块内存区域,bss段属于静态内存分配,地址不变
确定偏移:
为10
把pwnme的地址输进去,偏移10 将8利用 %n带入到pwnme的地址,所以变量pwnme就是8了
poc:
from pwn import * |