Fundamentals and Review of ENPM691
https://hackmd.io/@paolieri/x86_64
https://flint.cs.yale.edu/cs421/papers/x86-asm/asm.html
Certain Registers are callee-owned (owned by the function that just got called)
Certain Registers are caller-owned (owned by the function that calls the other function)
If A calls B, A is the caller and B is the callee.
Based on the calling convention (will explain later).
Also called the SYSTEM V calling convention
Function Parameters
Return value is stored in rax
Other things to know:
Floating point arguments: XMM0 - XMM7
Determining the place in memory where we want to get data (aka finding the address we want to access).
Terminology
rax
, rbx
, &c).Displacement
Base
Base + Index
Base + Displacement
Base + Index + Displacement
Base + (Index * Scale)
(Index * Scale) + Displacement
Base + (Index * Scale) + Displacement
In depth (and in intel Syntax) https://blog.yossarian.net/2020/06/13/How-x86_64-addresses-memory
movl $1, 0x604892 # direct (address is constant value)
movl $1, (%rax) # indirect (address is in register %rax)
movl $1, -24(%rbp) # indirect with displacement
(address = base %rbp + displacement -24)
movl $1, 8(%rsp, %rdi, 4) # indirect with displacement and scaled-index
(address = base %rsp + displ 8 + index %rdi * scale 4)
movl $1, (%rax, %rcx, 8) # (special case scaled-index, displ assumed 0)
movl $1, 0x8(, %rdx, 4) # (special case scaled-index, base assumed 0)
movl $1, 0x4(%rax, %rcx) # (special case scaled-index, scale assumed 1)
Credit: Kenneth Miltenberger
Credit: Kenneth Miltenberger
Credit: Kenneth Miltenberger
Application
Write()
Read()
sys_write
sys_read
Firmware
EXT4, FAT32 ...
Disk
Partition
Block
Block
Block
Block
https://en.wikipedia.org/wiki/Inode_pointer_structure
See what you can discover about your user directory. Based on what we found.
When would you compile shellcode vs use pwntools shellcraft?
gcc -nostdlib-static shellcode.s -o shellcode-elf #This assembles it into C
objcopy --dump-section .text=shellcode-raw shellcode-elf #We extract the shellcode from the assembled ELF file
Shellcode
NOP Sled
Return Address
Shellcode
NOP Sled
Return Address
int some_function()
{
char buff[128];
gets(buff);
printf("%s\n", buffer);
return 0;
}
int main() {
int a = 0;
scanf("%d", &a);
printf("a = %d\n", a);
printf("Adding 1 to a...\n");
a = a + 1;
printf("a = %d\n", a);
return 0;
}
void another_function(char *arg1)
{
char name[128];
strcpy(name, arg1);
printf("Hello %s\n", name);
}
int main(int argc, char **argv)
{
if (argc < 2) # checking arg length
{
printf("Usage: %s <your name>\n", argv[0]);
return 0;
}
another_function(argv[1]); # Call the vulnerable function
return 0;
}
int some_function()
{
char buff[128];
gets(buff);
printf("%s\n", buffer);
return 0;
}
int some_function()
{
char buff[128];
gets(buff);
printf("%s\n", buffer);
return 0;
}
pwnlib
or any of the submodules should have any significant side-effects (besides e.g. caching).pwnlib.util.packing
simply by doing import pwnlib.util
.python3 -m pip install venv
or sudo apt install python3-venv
source /path/to/venv/bin/activate
python3 -m pip install pwntools
pwn
or checksec
pwn template --host <ip> --port <port> <binary> > solve.py
checksec <binary>
wittsend@wittsend-virtual-machine:[~/Documents/redteam-ctf/reach]
$ pwn template Reach
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# This exploit template was generated via:
# $ pwn template Reach
from pwn import *
# Set up pwntools for the correct architecture
exe = context.binary = ELF(args.EXE or 'Reach')
# Many built-in settings can be controlled on the command-line and show up
# in "args". For example, to dump all data sent/received, and disable ASLR
# for all created processes...
# ./exploit.py DEBUG NOASLR
def start(argv=[], *a, **kw):
'''Start the exploit against the target.'''
if args.GDB:
return gdb.debug([exe.path] + argv, gdbscript=gdbscript, *a, **kw)
else:
return process([exe.path] + argv, *a, **kw)
# Specify your GDB script here for debugging
# GDB will be launched if the exploit is run via e.g.
# ./exploit.py GDB
gdbscript = '''
tbreak main
continue
'''.format(**locals())
#===========================================================
# EXPLOIT GOES HERE
#===========================================================
# Arch: amd64-64-little
# RELRO: Full RELRO
# Stack: No canary found
# NX: NX enabled
# PIE: PIE enabled
io = start()
shellcode = asm(shellcraft.sh())
payload = fit({
32: 0xdeadbeef,
'iaaa': [1, 2, 'Hello', 3]
}, length=128)
io.send(payload)
flag = io.recv(...)
log.success(flag)
io.interactive()
Go to pwn.college ENPM809V introduction module and do the classwork! Objective is to do a ret2win: buffer overflow and call another function within the same program.
Some of the slides were derived from Drake Petersen who gave me permission to use them for the course.