Binary
See my note on Software Security.
Intro book to to binary exploitation / reverse engineering.
Pwntools Cheatsheet
Syscalls for x64
Syscalls for x86
Syscalls for arm64
Compare tools on the forefront of static analysis in your web browser
Binary Ninja
To be expanded with PEDA, GEF or PWNDBG.
Start
gdb <ELF>
Run gdb on that program. Be careful with addresses (it would be better to use PID).
gdb --pid <PID>
Run gdb on a process. Run the program in the background, get PID and provide it to gdb.
gdb --args <ELF> <ARGs>
Run gdb on that program passing it arguments.
Execution
file <ELF>
Load the program to analyze
set args <ARGs>
Set the arguments to use on each bugger run.
r
Run
r <ARGs>
Run with arguments
r ${python3 -c ‘print "\xBYTES"’}
Run with byte arguments using Python
r ${echo -e “\xBYTES”}
run with byte arguments using Echo
Breakpoints
b <function>
b *<address>
Set a breakpoint.
Also possible to do: b *main+10
i b
Info breakpoint
enable <ID>
Enable breakpoints. If no ID is specified, enable all breakpoints.
disable <ID>
Disable breakpoints. If no ID is specified, disable all breakpoints.
d <ID>
Delete breakpoint If no ID is specifyied, deletes all breakpoints.
c
Continue. Normal execution.
s
Step. IN function.
n
Next. NO IN function.
finish
Continue until the current function returns.
k
Kill. Stop the current execution.
Visualization
disassemble <FUNCTION>
Get assembly and their memory addresses.
i fu
Get the list of program functions with their addresses.
bt [full]
Show backtrace (function calls list).
With full
print even the local variables of each frame, if you have access to them.
i s
Info Stack Frame.
i f
Info Current Stack Frame. (ex. $RIP in BOF)
i r
i all-r
Info Registers.
i dll
list of used DLLs
p/<F> <expr>
Print what you want in the specified format <F>
.
ex. p/x $esp
p/x $esp+8
p <FUN>
p <VAR>
x/<N><F><U> <addr>
display/<N><F><U> <addr>
As x/ but are saved and printed/displayed at each step.
i display
undisplay <ID>
enable display <ID>
disable display <ID>
If you don't put ID it applies to all.
ex. display/5i $pc
(next 5 instruction)
Format
a
Pointer.c
Read as integer, print as character.d
Integer, signed decimal.f
Floating point number.o
Integer, print as octal.s
String.t
Integer, print as binary (t = "two").u
Integer, unsigned decimal.x
Integer, print as hexadecimal.i
Disassembly.
Edit memory
set {type}address = value
Change the value of the addresses.
ex. set{int}0x650000 = 0x42
set{char[1]}0x650000 = 0x42
set variable = value
Change the value of variables
set $reg = value
Change the value of the registers
set *address = value
Change the value of an address
Utility
call <FUNCTION>()
Call function.
ex. call (void)win()
echo $((16#<NUM>))
From bash convert hex to decimal.
r << <CommandFile>
It is possible to specify a file with the inputs that should be given to the program in read, scanf, etc.
Like cat <CommandFile> | ./<ELF>
j *<EXPRESSION>
Jump and force execution to a specific address (*addr, *$reg, function).
pwndbg
pwndbg [<TOPIC>]
Print info about pwndbg commands
vmmap
Display memory mappings information
context [<SECTION>]
Display context or a given context section (regs, disasm, args, code, stack, backtrace, expressions, ghidra, threads)
search <WHAT>
Search memory for a given value
telescope <WHERE> [<COUNT>]
Examine memory dereferencing valid pointers
hexdump <WHERE> [<COUNT>]
Print hexdump of given address
xinfo <WHERE>
Show offsets of the specified address from various useful locations
retaddr
Print return addresses on the stack
canary
Print the global stack canary/cookie value and finds canaries on the stack
xuntil
Continue until an address or function
nextcall
Continue to next call instruction
nextjmp
Continue to next jump instruction
nextret
Continue to next return-like instruction
stepret
Step until a ret instruction is found
checksec
Print binary mitigations status
piebase
Print the relocated binary base address
got
Print symbols in the .got section
gotplt
Print symbols in the .got.plt section
plt
Print symbols in the .plt section
tls
Print thread local storage address
distance <WHERE1> <WHERE2>
Compute difference between two addresses
procinfo
Display process information
heap_config
Show glibc allocator hacking configuration
heap
Iteratively print chunks on heap (glibc only)
vis_heap_chunks
Visualize chunks on a heap
try_free <ADDRESS>
Check what would happen if free was called with given address
checksec <ELF>
pwn checksec <ELF>
Context
Architecture
context.arch = '<ARCH>'
'aarch64'
, 'arm'
, 'i386'
, 'amd64'
Log Output
context.log_level = '<VALUE>'
'debug'
, 'info'
, 'warn'
, 'error'
Endianness
context.endian = '<ENDIANNESS>'
'big'
, 'little'
Start
ELF
elf = ELF('<PATH_BINARY>')
libc = ELF("./libc.so.6")
Process
p = process('<PATH_BINARY>')
Remote
p = remote('<IP/DOMAIN>', PORT)
Hybrid
elf = ELF('<PATH_BINARY>')
p = elf.process()
Debugger
p = gdb.debug('<PATH_BINARY>', aslr=False, gdbscript='b *main+123')
Encoding e Packing
Hex
enhex(b'/flag')
('2f666c6167')
unhex('2f666c6167')
(b'/flag')
Base64
b64e(b'/flag')
('L2ZsYWc=')
b64d('L2ZsYWc=')
(b'/flag')
Packing
p32(0x41424344)
(b'\x44\x43\x42\x41')
p8
, p16
, p64
Unpacking
u32(b'\x44\x43\x42\x41')
(0x41424344)
u8
, u16
, u64
Address
Function address
address = elf.sym['<Name_Function>']
address = elf.symbols.<Name_Function>
address = elf.plt[’<Name_Function>’]
(in PLT)
address = elf.got[’<Name_Function>’]
(in GOT)
String address
address = next(elf.search(b'<STRING>'))
Or with ghidra in .rodata
, .text
Cyclic
Create Search String
cyclic(16)
(b'aaaabaaacaaadaaa')
cyclic(16, n=8)
(b'aaaaaaaabaaaaaaa')
Find Offset
cyclic_find(0x61616164)
(12)
cyclic_find(0x6161616161616162, n=8)
(8)
cyclic_find(io.corefile.fault_addr, n=8)
(in BOF)
In BOF use setuid=False
in p = process()
Shellcode
Shellcraft, must be NULL-free.
Assembly
code = shellcraft.cat('/flag')
code = shellcraft.amd64.linux.sh()
Bytecode
shellcode = asm(code)
(use the context architecture)
shellcode = asm(code, arch='x86_64')
Start
rop = ROP(elf)
rop = ROP(elf, badchars=b'\n')
(char not to be used in the chain)
rop = ROP([elf, libc])
(specify double elf)
Extract Gadget
pop_ = rop.find_gadget(['pop <REG>', 'ret']).address
pop_ = rop.<REG>.address
or ROPgadget.
ROP chain
rop.call(<ADDR_FUNCTION>, [<ADDR_ARG1>, ... ])
rop.puts(); rop.main()
(adds puts and main to the chain) rop.chain()
(builds the chain with the elements called before) rop.dump()
(text representation, to be put in log.info(X)
)
rop.clear()
(clears the rop chain)
rop.execve(next(libc.search(b'/bin/sh\0')), 0, 0)
(calls execv with parameters)
Set Base Address (ex. libc)
libc = ELF(<PATH_LIBC>)
(ex ./glibc/libc.so.6)
libc.address = <INT_ADDRESS_BASE>
rop_libc = ROP(libc)
(after set base libc)
Format String
%p
Pointer
%s
String
%d
Int
%x
Hex
%c
Char
%n
Writes the number of characters printed in the specified pointer.
%n
= int (8 byte)
%hn
= short (4 byte)
%hhn
= byte (1 byte)
%<P>x
Specifies the precision <P> (filled with 0)
%<N>$x
Take the <N>-th argument
fmtstr_payload(offset, writes, numbwritten=0, write_size='byte')
offset
: Offset to the bufferwrites
: Dictionary with address:value{addr: value, addr2: value2, etc.}
numbwritten
: Number of bytes already written by printf() ex.printf(hello <VAR>)
= 6write_size
: The write size: byte, short or int (hhn, hn or n)
Note: Set the right <ARCH>
Last updated
Was this helpful?