Before We Start
Bash
$ echo 'ABC' | hexdump -C
00000000 41 42 43 0a |ABC.|
00000004
$ echo -n 'ABC' | hexdump -C
00000000 41 42 43 |ABC|
00000003
Quoting characters
# let echo $i = 2
$ echo 'A"B"C' # A"B"C
$ echo '$i ${i} $((i))' # $i ${i} $((i))
$ echo "$i ${i} $((i))" # 2 2 2
$ echo "\$i \${i} \$((i))" # $i ${i} $((i))
#--------------------------
# why \\$ ??
$ VAR=`python3 -c "print('%${i}\\$08x')"`; echo $VAR # %2$08x
Python
$ python3 -c "print('ABC')" | hexdump -C
00000000 41 42 43 0a |ABC.|
00000004
$ python3 -c "print('ABC', end='')" | hexdump -C
00000000 41 42 43 |ABC|
00000003
this is the most used method by me !!
handles the bytes and strips the newline
$ python3 -c "import sys; sys.stdout.buffer.write(b'ABC')" | hexdump -C
00000000 41 42 43 |ABC|
00000003
# notice we print bytes not strings
$ python2 -c "import sys; sys.stdout.write(b'ABC')" | hexdump -C
00000000 41 42 43 |ABC|
00000003
GCC
gcc options and what they do:
-pie # Enable ASLR (Default)
-no-pie # Disable ASLR
-Wl,-z,relro,-z,now # Full RELRO
-Wl,-z,relro,-z # Partial RELRO (Default)
-Wl,-z,norelro # No RELRO
-fstack-protector # Enable canaries
-fno-stack-protector # Disable canaries
-z execstack # NX disabled
-s # Stripped, remove the relocation information along with the symbol table
-static # Statically link all the included libraries
-m32
-m64
PwnTools
Pwntools Cheatsheet
from pwn import *
import os
args = ['A']*100
args[65] = '\x00'
args[66] = '\x20\x0a\x0d'
args[67] = '4444'
r1, w1 = os.pipe()
os.write(w1, '\x00\x0a\x00\xff')
# r2, w2 = os.pipe()
# os.write(w2, '\x00\x0a\x02\xff')
open('STDERR', 'wb').write(b'\x00\x0a\x02\xff')
with open('\x0a', 'w') as f:
f.write('\x00\x00\x00\x00')
p = process(executable='/home/input2/input',
argv=args,
stdin=r1,
stderr=open('STDERR', 'rb'),
env={'\xde\xad\xbe\xef' :'\xca\xfe\xba\xbe'}
aslr=True)
conn = remote('localhost', 4444)
conn.sendline('\xde\xad\xbe\xef')
p.interactive()
GDB
install gdb plugines :: https://infosecwriteups.com/pwndbg-gef-peda-one-for-all-and-all-for-one-714d71bf36b8 & Combining all in One
and splitmid :: https://github.com/jerdna-regeiz/splitmind
$ cat ~/.gdbinit
source /home/o54ma/pwndbg/gdbinit.py
set context-clear-screen on
set follow-fork-mode parent
source /home/o54ma/splitmind/gdbinit.py
python
import splitmind
(splitmind.Mind()
.tell_splitter(show_titles=True)
.tell_splitter(set_title="Main")
.right(display="stack", size="30%")
.above(of="main", display="disasm", size="60%", banner="top")
.show("code", on="disasm", banner="none")
.right(cmd='tty; tail -f /dev/null', size="50%", clearing=False)
.tell_splitter(set_title='Input / Output')
.above(display="backtrace", size="75%")
.above(display="legend", size="22")
.show("regs", on="legend")
.below(of="stack", cmd="ipython", size="30%")
).build(nobanner=True)
end
set context-code-lines 30
set context-source-code-lines 30
set context-stack-lines 40
set context-sections "regs args code disasm stack backtrace"
$ cat ~/gdb-default
$ tmux
$ gcc code.c -o binaryFile [-m32] [-g]
$ gdb [binaryFile] -x [FILE to Execute GDB commands]
pwndbg> file binaryFile
pwndbg> disassemble *FuncName # or an addr
pwndbg> b *FunctionName[+Num] # add a break point at a func
pwndbg> info b # list break points
pwndbg> clear *FunctionName[+Num] # delete break point by Func name
pwndbg> delete <Num> # delete break point by it's number
pwndbg> disable <Num> # turn a breakpoint off
pwndbg> enable <Num> # turn a breakpoint back on
pwndbg> run
pwndbg> run arg1 arg2 ... # arg could be a shell code $(cyclic 50)
pwndbg> run <<< arg
pwndbg> n [Num] # step over (next instr)
pwndbg> s [Num] # step into
pwndbg> finish # finish current function's execution
pwndbg> kill # kill current executing program
pwndbg> info locals # print automatic variables in frame (when compiled with -g option )
pwndbg> info args # print function parameters
pwndbg> p &VarName # print var addr , Ex:: p &Struct.VarName
pwndbg> p/x &FunName # print fun addr , Ex:: p &main
pwndbg> whatis <expression> # print the type of expression => {VarName, Addr, ...}
Examine memory: x/FMT &ADDRESS
FMT is a repeat count followed by a format letter and a size letter.
-
Format letters are
o(octal),x(hex),d(decimal),u(unsigned decimal),t(binary),f(float),a(address),i(instruction),c(char),s(string)andz(hex, zero padded on the left). -
Size letters are
b(byte),h(halfword),w(word),g(giant, 8 bytes). -
The specified number of objects of the specified size are printed according to the format. If a
negativenumber is specified, memory is examined backward from the address.
pwndbg> x/x &gx
pwndbg> x/4wx &main
pwndbg> x/gf &gd1
pwndbg> cwatch execute "x\w 0xffffcfbc" # Adds an expression to be shown on context.
pwndbg> watch *Addr # breaks on write at Addr
pwndbg> rwatch *Addr # breaks on read
pwndbg> awtach *Addr # breaks on read or write
pwndbg> info watchpoints # show current watchpoints
# Miscellaneous
(gdb) define command ... end # define user command
*(gdb) RETURN # repeat last command
*(gdb) shell command args # execute shell command
*(gdb) source file # load gdb commands from file
*(gdb) quit # or exit
in pwngdb .. in tmux .. you can close any unwanted screen by selecting it and clicking ctrl+c
set disable-randomization off
If your bug disappears when you run the program under GDB, that might be because GDB by default disables the address randomization on platforms, such as GNU/Linux, which do that for stand-alone programs. Use set disable-randomization off to try to reproduce such elusive bugs.
On targets where it is available, virtual address space randomization protects the programs against certain kinds of security attacks. In these cases the attacker needs to know the exact location of a concrete executable code. Randomizing its location makes it impossible to inject jumps misusing a code at its expected addresses.
Heap (malloc storage), stack and custom mmap areas are always placed randomly (as long as the randomization is enabled).
sudo bash -c "echo 0 > /proc/sys/kernel/randomize_va_space"
sudo bash -c "echo 2 > /proc/sys/fs/suid_dumpable"