2015年2月20日 星期五

[Embedded] 一個練習組合語言的小遊戲 -- Defusing bomb (part 2)

遊戲說明請參考  http://wiki.csie.ncku.edu.tw/embedded/Lab34


以下記錄自己的解答方式。本篇僅紀錄 part2 的解法,透過此練習可學得如何利用 stack overflow 來執行 shellcode。

[Embedded] 一個練習組合語言的小遊戲 -- Defusing bomb (part 1)

此遊戲的設計目的是要讓使用者學會利用 gdb 與 objdump 分析執行檔,並學習 hack 程式!!!! 遊戲說明請參考  http://wiki.csie.ncku.edu.tw/embedded/Lab34

以下記錄自己的解答方式。本篇僅紀錄 part1 的解法,簡單來說就是使用gdb找出正確輸入值,避免程式進入 explode_bomb()。

2015年2月7日 星期六

[Embedded] GDB script -- generate a basic report per core file

wikibook 針對 core dump 使用,提供了幾個有用的 script,其中有個自動產生報表的方式對我幫助很大。摘錄如下:


#!/bin/bash

#
# A script to extract core-file informations
#


if [ $# -ne 1 ]
then
echo "Usage: `basename $0` "
exit -1
else
binimg=$1
fi


# Today and yesterdays cores
cores=`find . -name '*.core' -mtime -1`

#cores=`find . -name '*.core'`


for core in $cores
do
gdblogfile="$core-gdb.log"
rm $gdblogfile

bininfo=`ls -l $binimg`
coreinfo=`ls -l $core`

gdb -batch \
-ex "set logging file $gdblogfile" \
-ex "set logging on" \
-ex "set pagination off" \
-ex "printf \"**\n** Process info for $binimg - $core \n** Generated `date`\n\"" \
-ex "printf \"**\n** $bininfo \n** $coreinfo\n**\n\"" \
-ex "file $binimg" \
-ex "core-file $core" \
-ex "bt" \
-ex "info proc" \
-ex "printf \"*\n* Libraries \n*\n\"" \
-ex "info sharedlib" \
-ex "printf \"*\n* Memory map \n*\n\"" \
-ex "info target" \
-ex "printf \"*\n* Registers \n*\n\"" \
-ex "info registers" \
-ex "printf \"*\n* Current instructions \n*\n\"" -ex "x/16i \$pc" \
-ex "printf \"*\n* Threads (full) \n*\n\"" \
-ex "info threads" \
-ex "bt" \
-ex "thread apply all bt full" \
-ex "printf \"*\n* Threads (basic) \n*\n\"" \
-ex "info threads" \
-ex "thread apply all bt" \
-ex "printf \"*\n* Done \n*\n\"" \
-ex "quit"
done

Reference:
http://en.m.wikibooks.org/wiki/Linux_Applications_Debugging_Techniques/Core_files

2015年2月6日 星期五

[Embedded] GDB script -- check stack when stack corrupt

若使用 gdb 檢查 core dump 時,發現 stack corrupt,此時該如何看到正確的 stack trace 呢?

問題情況舉例如下:(使用 stackoverflow 的例子做說明)

Program received signal SIGSEGV, Segmentation fault.
0x00000002 in ?? ()
(gdb) bt
#0  0x00000002 in ?? ()
#1  0x00000001 in ?? ()
#2  0xbffff284 in ?? ()
Backtrace stopped: previous frame inner to this frame (corrupt stack?)

問題解決方式:(假設系統架構為 Linux 32-bit x86)

1. 首先必須先大概了解 Linux 作業系統內的虛擬記憶體配置
例如:
stack 會位於 0xBFxxxxxx 附近
text (程式碼) 會從 0x08048000 開始增加
因此 0xbffff284可能是正確的 stack位址,而 0x00000001 與 0x00000002 並非正確的 stack 位址,此時 stack 已經亂掉。
若對於 stack 使用有疑問,可以直接參考此範例。 

2. 以上述的錯誤位址為例,這個問題有可能因為呼叫function 時,指向了錯誤的 function pointer。
An indirect call instruction just pushes the PC after the call onto the stack and then sets the PC to the target value (bogus in this case), so if this is what happened, you can easily undo it by manually popping the PC off the stack. In 32-bit x86 code you just do:

(gdb) set $pc = *(void **)$sp
(gdb) set $sp = $sp + 4

3. 另外一個可能是正確的 stack 被覆蓋了。此時基本處理原則是將整個 stack 都尋找一遍,直到找到對應的程式進入點為止 (例如:main())。
例如: (gdb) x/256wa $sp 
其基本原理為從目前的 sp register 開始,每隔一個 word(4bytes),印出對應的位址,若有對應的 symbol 會一併列印,持續尋找 256 words。

4. 若想要將 stack 狀態寫入檔案,可以參考 Loda's blog 的 GDB 筆記,其基本原理與 x/256wa $sp 相同,不過產生出的 log 較方便閱讀。摘錄如下:
file executable_file_build_with_debug_flag
set solib-search-path builtin-symbol-library-file-path
set solib-absolute-prefix builtin-symbol-library-filepath-prefix
core core_dump_file
set print symbol-filename on
set logging file stack-out.txt
set logging on
set $stack_addr=$sp
printf "Start to decode tack\n"
set $i=0
while($i<256 br=""> printf "i:%ld stack_addr:%xh\n",$i,$stack_addr
print /a *(int *) $stack_addr
set $stack_addr = $stack_addr +4
set $i = $i + 1
end
printf "End\n"
set logging off

Reference:

[Embedded] GDB script -- check deadlock caused by mutex

Gdb scripts can be used to fix bugs easily. So I collect some gdb script here as reference.
The first script is used to find the deadlock caused by mutex misuse.

Reference : Debug Hacks

1. For example: debug.cmd
set pagination offset logging file debug.log
set logging overwrite
set logging on
start
set $addr1 = pthread_mutex_lock
set $addr2 = pthread_mutex_unlock
b *$addr1
b *$addr2
while 1
   c
   if $pc != $addr1 & $pc != $addr2
      quit
   end
   printf "## addr : %08x\n", *(int *)($esp+4)
   bt
end 
NOTE: when you press ctrl+c, this script will quit.

2. Usage
$ gdb ./a.out -x debug.cmd