Волан-де-Морт спрятал свою расколотую душу в семи крестражах.
Найдите все крестражи и РАЗДЕЛАЙТЕ их!
автор: jiwon choi
ssh [email protected] -p2222 (pw: гость)
Хоркруксы - это 32-битный двоичный файл ELF, который инициализирует в памяти 7 хоркруксов Волан-де-Морта. У Horcuxes есть случайные константы, которые нам нужно вывести, чтобы победить Волан-де-Морта.
horcruxes@prowl:~$ ./horcruxes Voldemort concealed his splitted soul inside 7 horcruxes. Find all horcruxes, and destroy it! Select Menu:222 How many EXP did you earned? : 2222 You'd better get more experience to kill Voldemort
Давайте посмотрим, что такое EXP и как мы можем предсказать, что он убьет Волдеморта. Это основная подпрограмма:
gdb-peda$ disassemble main Dump of assembler code for function main: 0x0809ff24 <+0>: lea ecx,[esp+0x4] 0x0809ff28 <+4>: and esp,0xfffffff0 0x0809ff2b <+7>: push DWORD PTR [ecx-0x4] 0x0809ff2e <+10>: push ebp 0x0809ff2f <+11>: mov ebp,esp 0x0809ff31 <+13>: push ecx 0x0809ff32 <+14>: sub esp,0x14 0x0809ff35 <+17>: mov eax,ds:0x80a2064 0x0809ff3a <+22>: push 0x0 0x0809ff3c <+24>: push 0x2 0x0809ff3e <+26>: push 0x0 0x0809ff40 <+28>: push eax 0x0809ff41 <+29>: call 0x809fcf0 <setvbuf@plt> 0x0809ff46 <+34>: add esp,0x10 0x0809ff49 <+37>: mov eax,ds:0x80a2060 0x0809ff4e <+42>: push 0x0 0x0809ff50 <+44>: push 0x2 0x0809ff52 <+46>: push 0x0 0x0809ff54 <+48>: push eax 0x0809ff55 <+49>: call 0x809fcf0 <setvbuf@plt> 0x0809ff5a <+54>: add esp,0x10 0x0809ff5d <+57>: sub esp,0xc 0x0809ff60 <+60>: push 0x3c 0x0809ff62 <+62>: call 0x809fc90 <alarm@plt> 0x0809ff67 <+67>: add esp,0x10 0x0809ff6a <+70>: call 0x80a0324 <hint> 0x0809ff6f <+75>: call 0x80a0177 <init_ABCDEFG> 0x0809ff74 <+80>: sub esp,0xc 0x0809ff77 <+83>: push 0x0 0x0809ff79 <+85>: call 0x809fc20 <seccomp_init@plt> 0x0809ff7e <+90>: add esp,0x10 0x0809ff81 <+93>: mov DWORD PTR [ebp-0xc],eax 0x0809ff84 <+96>: push 0x0 0x0809ff86 <+98>: push 0xad 0x0809ff8b <+103>: push 0x7fff0000 0x0809ff90 <+108>: push DWORD PTR [ebp-0xc] 0x0809ff93 <+111>: call 0x809fc60 <seccomp_rule_add@plt> 0x0809ff98 <+116>: add esp,0x10 0x0809ff9b <+119>: push 0x0 0x0809ff9d <+121>: push 0x5 0x0809ff9f <+123>: push 0x7fff0000 0x0809ffa4 <+128>: push DWORD PTR [ebp-0xc] 0x0809ffa7 <+131>: call 0x809fc60 <seccomp_rule_add@plt> 0x0809ffac <+136>: add esp,0x10 0x0809ffaf <+139>: push 0x0 0x0809ffb1 <+141>: push 0x3 0x0809ffb3 <+143>: push 0x7fff0000 0x0809ffb8 <+148>: push DWORD PTR [ebp-0xc] 0x0809ffbb <+151>: call 0x809fc60 <seccomp_rule_add@plt> 0x0809ffc0 <+156>: add esp,0x10 0x0809ffc3 <+159>: push 0x0 0x0809ffc5 <+161>: push 0x4 0x0809ffc7 <+163>: push 0x7fff0000 0x0809ffcc <+168>: push DWORD PTR [ebp-0xc] 0x0809ffcf <+171>: call 0x809fc60 <seccomp_rule_add@plt> 0x0809ffd4 <+176>: add esp,0x10 0x0809ffd7 <+179>: push 0x0 0x0809ffd9 <+181>: push 0xfc 0x0809ffde <+186>: push 0x7fff0000 0x0809ffe3 <+191>: push DWORD PTR [ebp-0xc] 0x0809ffe6 <+194>: call 0x809fc60 <seccomp_rule_add@plt> 0x0809ffeb <+199>: add esp,0x10 0x0809ffee <+202>: sub esp,0xc 0x0809fff1 <+205>: push DWORD PTR [ebp-0xc] 0x0809fff4 <+208>: call 0x809fc80 <seccomp_load@plt> 0x0809fff9 <+213>: add esp,0x10 0x0809fffc <+216>: call 0x80a0009 <ropme> 0x080a0001 <+221>: mov ecx,DWORD PTR [ebp-0x4] 0x080a0004 <+224>: leave 0x080a0005 <+225>: lea esp,[ecx-0x4] 0x080a0008 <+228>: ret End of assembler dump. gdb-peda$ [main_tmux<g-off.tower-research.com[adogra]
init_ABCDEFG инициализирует 7 наших крестражей в памяти.
gdb-peda$ disassemble init_ABCDEFG Dump of assembler code for function init_ABCDEFG: 0x080a0177 <+0>: push ebp 0x080a0178 <+1>: mov ebp,esp 0x080a017a <+3>: sub esp,0x18 0x080a017d <+6>: sub esp,0x8 0x080a0180 <+9>: push 0x0 0x080a0182 <+11>: push 0x80a0577 0x080a0187 <+16>: call 0x809fcc0 <open@plt> 0x080a018c <+21>: add esp,0x10 0x080a018f <+24>: mov DWORD PTR [ebp-0xc],eax 0x080a0192 <+27>: sub esp,0x4 0x080a0195 <+30>: push 0x4 0x080a0197 <+32>: lea eax,[ebp-0x10] 0x080a019a <+35>: push eax 0x080a019b <+36>: push DWORD PTR [ebp-0xc] 0x080a019e <+39>: call 0x809fc30 <read@plt> 0x080a01a3 <+44>: add esp,0x10 0x080a01a6 <+47>: cmp eax,0x4 0x080a01a9 <+50>: je 0x80a01c5 <init_ABCDEFG+78> 0x080a01ab <+52>: sub esp,0xc 0x080a01ae <+55>: push 0x80a0584 0x080a01b3 <+60>: call 0x809fca0 <puts@plt> 0x080a01b8 <+65>: add esp,0x10 0x080a01bb <+68>: sub esp,0xc 0x080a01be <+71>: push 0x0 0x080a01c0 <+73>: call 0x809fcb0 <exit@plt> . . 0x080a01df <+104>: add esp,0x10 0x080a01e2 <+107>: call 0x809fd00 <rand@plt> 0x080a01e7 <+112>: imul edx,eax,0xdeadbeef 0x080a01ed <+118>: cmp edx,0xcafebabe 0x080a01f3 <+124>: setae al 0x080a01f6 <+127>: movzx eax,al 0x080a01f9 <+130>: imul eax,eax,0xcafebabe 0x080a01ff <+136>: sub edx,eax 0x080a0201 <+138>: mov eax,edx 0x080a0203 <+140>: mov ds:0x80a2088,eax 0x080a0208 <+145>: call 0x809fd00 <rand@plt> 0x080a020d <+150>: imul edx,eax,0xdeadbeef 0x080a0213 <+156>: cmp edx,0xcafebabe 0x080a0219 <+162>: setae al 0x080a021c <+165>: movzx eax,al 0x080a021f <+168>: imul eax,eax,0xcafebabe 0x080a0225 <+174>: sub edx,eax 0x080a0227 <+176>: mov eax,edx 0x080a0229 <+178>: mov ds:0x80a2070,eax 0x080a022e <+183>: call 0x809fd00 <rand@plt> 0x080a0233 <+188>: imul edx,eax,0xdeadbeef 0x080a0239 <+194>: cmp edx,0xcafebabe 0x080a023f <+200>: setae al 0x080a0242 <+203>: movzx eax,al 0x080a0245 <+206>: imul eax,eax,0xcafebab . 0x080a02c1 <+330>: mov ds:0x80a2074,eax 0x080a02c6 <+335>: call 0x809fd00 <rand@plt> 0x080a02cb <+340>: imul edx,eax,0xdeadbeef 0x080a02d1 <+346>: cmp edx,0xcafebabe 0x080a02d7 <+352>: setae al 0x080a02da <+355>: movzx eax,al 0x080a02dd <+358>: imul eax,eax,0xcafebabe 0x080a02e3 <+364>: sub edx,eax 0x080a02e5 <+366>: mov eax,edx 0x080a02e7 <+368>: mov ds:0x80a207c,eax 0x080a02ec <+373>: mov edx,DWORD PTR ds:0x80a2088 0x080a02f2 <+379>: mov eax,ds:0x80a2070 0x080a02f7 <+384>: add edx,eax 0x080a02f9 <+386>: mov eax,ds:0x80a2084 0x080a02fe <+391>: add edx,eax 0x080a0300 <+393>: mov eax,ds:0x80a206c 0x080a0305 <+398>: add edx,eax 0x080a0307 <+400>: mov eax,ds:0x80a2080 0x080a030c <+405>: add edx,eax 0x080a030e <+407>: mov eax,ds:0x80a2074 0x080a0313 <+412>: add edx,eax 0x080a0315 <+414>: mov eax,ds:0x80a207c 0x080a031a <+419>: add eax,edx 0x080a031c <+421>: mov ds:0x80a2078,eax 0x080a0321 <+426>: nop 0x080a0322 <+427>: leave 0x080a0323 <+428>: ret
Функция init считывает некоторые байты из / dev / urandom, а затем выполняет арифметические операции и устанавливает константы в памяти. В конце концов, он суммирует эти константы и сохраняет их в ds: 0x80a2078.
После инициализации и настройки профилей seccomp. ropme называется следующим.
gdb-peda$ disassemble ropme Dump of assembler code for function ropme: 0x080a0009 <+0>: push ebp 0x080a000a <+1>: mov ebp,esp 0x080a000c <+3>: sub esp,0x78 0x080a000f <+6>: sub esp,0xc 0x080a0012 <+9>: push 0x80a050c 0x080a0017 <+14>: call 0x809fc40 <printf@plt> 0x080a001c <+19>: add esp,0x10 0x080a001f <+22>: sub esp,0x8 0x080a0022 <+25>: lea eax,[ebp-0x10] 0x080a0025 <+28>: push eax 0x080a0026 <+29>: push 0x80a0519 0x080a002b <+34>: call 0x809fd10 <__isoc99_scanf@plt> 0x080a0030 <+39>: add esp,0x10 0x080a0033 <+42>: call 0x809fc70 <getchar@plt> 0x080a0038 <+47>: mov edx,DWORD PTR [ebp-0x10] 0x080a003b <+50>: mov eax,ds:0x80a2088 0x080a0040 <+55>: cmp edx,eax 0x080a0042 <+57>: jne 0x80a004e <ropme+69> 0x080a0044 <+59>: call 0x809fe4b <A> 0x080a0049 <+64>: jmp 0x80a0170 <ropme+359> 0x080a004e <+69>: mov edx,DWORD PTR [ebp-0x10] 0x080a0051 <+72>: mov eax,ds:0x80a2070 0x080a0056 <+77>: cmp edx,eax 0x080a0058 <+79>: jne 0x80a0064 <ropme+91> 0x080a005a <+81>: call 0x809fe6a <B> 0x080a005f <+86>: jmp 0x80a0170 <ropme+359> 0x080a0064 <+91>: mov edx,DWORD PTR [ebp-0x10] 0x080a0067 <+94>: mov eax,ds:0x80a2084 0x080a006c <+99>: cmp edx,eax 0x080a006e <+101>: jne 0x80a007a <ropme+113> 0x080a0070 <+103>: call 0x809fe89 <C> . . . 0x080a00da <+209>: call 0x809fc40 <printf@plt> 0x080a00df <+214>: add esp,0x10 0x080a00e2 <+217>: sub esp,0xc 0x080a00e5 <+220>: lea eax,[ebp-0x74] 0x080a00e8 <+223>: push eax 0x080a00e9 <+224>: call 0x809fc50 <gets@plt> 0x080a00ee <+229>: add esp,0x10 0x080a00f1 <+232>: sub esp,0xc 0x080a00f4 <+235>: lea eax,[ebp-0x74] 0x080a00f7 <+238>: push eax 0x080a00f8 <+239>: call 0x809fd20 <atoi@plt> 0x080a00fd <+244>: add esp,0x10 0x080a0100 <+247>: mov edx,eax 0x080a0102 <+249>: mov eax,ds:0x80a2078 0x080a0107 <+254>: cmp edx,eax 0x080a0109 <+256>: jne 0x80a0160 <ropme+343> 0x080a010b <+258>: sub esp,0x8 0x080a010e <+261>: push 0x0 0x080a0110 <+263>: push 0x80a053c 0x080a0115 <+268>: call 0x809fcc0 <open@plt> 0x080a011a <+273>: add esp,0x10 0x080a011d <+276>: mov DWORD PTR [ebp-0xc],eax 0x080a0120 <+279>: sub esp,0x4 0x080a0123 <+282>: push 0x64 0x080a0125 <+284>: lea eax,[ebp-0x74] 0x080a0128 <+287>: push eax 0x080a0129 <+288>: push DWORD PTR [ebp-0xc] 0x080a012c <+291>: call 0x809fc30 <read@plt> 0x080a0131 <+296>: add esp,0x10 0x080a0134 <+299>: mov BYTE PTR [ebp+eax*1-0x74],0x0 0x080a0139 <+304>: sub esp,0xc 0x080a013c <+307>: lea eax,[ebp-0x74] 0x080a013f <+310>: push eax 0x080a0140 <+311>: call 0x809fca0 <puts@plt> 0x080a0145 <+316>: add esp,0x10 0x080a0148 <+319>: sub esp,0xc 0x080a014b <+322>: push DWORD PTR [ebp-0xc] 0x080a014e <+325>: call 0x809fd30 <close@plt> 0x080a0153 <+330>: add esp,0x10 0x080a0156 <+333>: sub esp,0xc 0x080a0159 <+336>: push 0x0 0x080a015b <+338>: call 0x809fcb0 <exit@plt> 0x080a0160 <+343>: sub esp,0xc 0x080a0163 <+346>: push 0x80a0544 0x080a0168 <+351>: call 0x809fca0 <puts@plt> 0x080a016d <+356>: add esp,0x10 0x080a0170 <+359>: mov eax,0x0 0x080a0175 <+364>: leave 0x080a0176 <+365>: ret
Целое число, которое мы указываем в приглашении меню, сравнивается с константами, которые мы видели ранее. Если мы предоставим правильное целое число, оно вызовет функцию (A, B, C,…), которая содержит крестраж.
В конце функции есть вызов gets (уязвимый !!), который спрашивает нас, сколько опыта мы получили. Затем EXP сравнивается с константой 0x80a2078, которая является просто суммой наших констант. Если сумма, которую мы предоставляем, верна, программа открывает нам флаг.
Давайте посмотрим, как разобрать эти функции (A, B, C,…):
gdb-peda$ disassemble A Dump of assembler code for function A: 0x0809fe4b <+0>: push ebp 0x0809fe4c <+1>: mov ebp,esp 0x0809fe4e <+3>: sub esp,0x8 0x0809fe51 <+6>: mov eax,ds:0x80a2088 0x0809fe56 <+11>: sub esp,0x8 0x0809fe59 <+14>: push eax 0x0809fe5a <+15>: push 0x80a03d0 0x0809fe5f <+20>: call 0x809fc40 <printf@plt> 0x0809fe64 <+25>: add esp,0x10 0x0809fe67 <+28>: nop 0x0809fe68 <+29>: leave 0x0809fe69 <+30>: ret End of assembler dump. gdb-peda$ x/1s 0x80a03d0 0x80a03d0: "You found \"Tom Riddle's Diary\" (EXP +%d)\n" gdb-peda$
Хорошо, он выплевывает константу и распечатывает, что мы нашли крестраж. Теперь задача ясна, нам нужно использовать переполнение в конце функции. Управляйте потоком выполнения и распечатывайте все крестражи один за другим.
Сначала я подумал, почему бы просто не перейти к той части кода, которая выдаёт флаг, нам не нужно будет утечка каких-либо констант. Интересно, что автор, наверное, уже думал об этом, если проверить адреса ropme. Адреса начинаются с 0x080a, 0xa - это символ новой строки, и после этого он перестанет получать наш ввод.
Мы можем легко вычислить адреса каждой из подпрограмм крестража. Просто взглянув на разборку. Все, что нам нужно сделать, это управлять EIP после вызова get, чтобы передать поток в A, B, C… G, а затем снова выполнить операцию и, наконец, ввести сумму утекших констант, чтобы получить флаг.
Вот и наш последний подвиг. Давайте посмотрим на это в действии:
Итак, мы идем! Я больше не ем бутылочку для малышей: D