Robert's GDB Walkthrough
break *main
info reg
print $rax
x/i $rip
x/10i $rip
disassemble main
disass my_func
p $rsp
x/4gx $rsp
x/4d $rsp
x/4u $rsp
x/4a $rsp
print/d $rsp
p/a $rsp
p/a *(long*) rsp
printf("%x", $5)
x/8i $rip-0x10
run <args>
display
display/4i $rip
ni
si
finish
info break
b *my_func+51
continue
quit
set $myvar=$rdi
p $myvar
set $rax=0
info reg
gdb -x my_script.gdb ./a.out
或者gdb -ex my_script.gdb ./a,out
或者在gdb命令列裡`source gdbscript`
b * main
commands
silent
p/a $rip
continue
end
run robert
q
設定~/.gdbinit
注意是'disassembly-flavor'不是'disassembly_flavor'
set disassembly-flavor intel
source /opt/gef/gef.py # plugin
一種不顯得pef輸出太多的方法:開一個fifo作為輸出,放在第二個視窗
There are a number of good gdb crash courses / reference manuals:
- Debugging with GDB
- Using GDB for Reverse Engineering
- gdb debugging full example
- pwndbg: a gdb extension (feature list)
- gef: another gdb extension (feature list)
- The course Debuggers 1012: Introductory GDB
Practices
run, continue, print/x $rax, x/10i $rip,x/10dx $rbp-22, set {int}($rbp-0x1c)=10,info display, undisplay 1,display/4gx $rsp,c, ni, si, finish,layout regs, disassem main,source myscript, call (void)win(),set $r=(int)read(3,$d, 1024)
``
level3: 看原始碼的時候想了好久,傳遞syscall的引數是rdi(fd), rsi(buff), rdx(count),但是隻看到了mov edx, 0x8
。忘掉了edx是rdx的sub register了
注意stack的方向和examine(print)的方向是相反的
You can examine the contents of memory using the x/<n><u><f> <address>
parameterized command. In this format <u>
is the unit size to display, <f>
is the format to display it in, and <n>
is the number of elements to display. Valid unit sizes are b
(1 byte), h
(2 bytes), w
(4 bytes), and g
(8 bytes). Valid formats are d
(decimal), x
(hexadecimal), s
(string) and i
(instruction). The address can be specified using a register name, symbol name, or absolute address. Additionally, you can supply mathematical expressions when specifying the address. For example, x/8i $rip
will print the next 8 instructions from the current instruction pointer. x/16i main
will print the first 16 instructions of main. You can also use disassemble main
, or disas main
for short, to print all of the instructions of main. Alternatively, x/16gx $rsp
will print the first 16 values on the stack. x/gx $rbp-0x32
will print the local variable stored there on the stack.
level4: 寫了好幾次,好幾次都在read之前讀了random value,或者寫錯了,最後實在受不了了用了set {int}($rbp-0x1c)=10
用ctrl+c在gdb可以暫停
注意display指令每一步都會重新列印,除非undisplay
info display, undisplay 1,display/4gx $rsp,c, ni, si, finish,layout regs
level5:gdbscript
~/.gdbinit
也是一個gdbscript,每次都會啟動
source gdbscript
start
break *main+42
commands
silent
set $local_variable = *(unsigned long long*)($rbp-0x32)
printf "Current value: %llx\n", $local_variable
continue
end
continue
level7: call (void)win()
level8: set $r=(int)read(3,$d, 1024)
The program being debugged was signaled while in a function called from GDB. GDB has restored the context to what it was before the call. To change this behavior use "set unwindonsignal off". Evaluation of the expression containing the function
1. 一開始以為可以忽略這個關閉訊號,後來發現不行,而且main就只是print後退出而已
2. 想從open之前的引數猜出flag檔案是什麼,但是列印出來的指令還以為還在win函式里面,怎麼讀`x\s $rip+0x777`都不行,後來發現其實已經跳回了main函式(正如提示所說)。此時計算就是當前指令前面的地址+x749,確實是"\flag"
3. 主要思路就是讀win原本的邏輯,對於讀flag必要的函式把原本地址引數算出來然後call對應的函式
4. geteuid返回結果為0有root特權
/dev/urandom
When read, the /dev/urandom device returns random bytes using a pseudorandom number generator seeded from the entropy pool. Reads from this device do not block (i.e., the CPU is not yielded), but can incur an appreciable delay when requesting large amounts of data.