Как стать автором
Обновить

Комментарии 13

Я пошёл путём статического анализа, после того, как сдампил расшифрованный кусок.
Ну и изредка gdb для проверок того, что всё верно понял (автоматом архитектура не менялась и сыпались ошибки, поэтому через несколько бряков пришлось работать):
Скрипт GDB
target remote localhost:1234
display/3i $pc
hbreak *0x04000148
break *0x200318
set arch i386:x86-64
break *0xFFFFF80000204E19 if $rdx == 12*0x18

Мнемоники инструкций ВМ даже не проверял, работу смотрел непосредственно в хэндлерах. Набросал скрипт который дизассемблит байт-код, даже интерпретатор влепил на всякий случай.
Скрипт дизассемблера
<?php

$code =
[
    [0x633272, '0x7233', '0x1505'],
...
    [0x726574, 0, 0]
];

$regs = [];

$regMap =
[
    0x7230 => 'r0',   // +0x0  PASSWORD
    0x7231 => 'r1',   // +0x8
    0x7232 => 'r2',   // +0x10
    0x7233 => 'r3',   // +0x18
    0x7234 => 'r4',   // +0x20 PASSWORD
    0x7235 => 'r5',   // +0x28
    0 => 'pc',        // +0x30
    0x726573 => 'r6', // +0x38
    0x727362 => 'r7'  // +0x40
];

function getByte($ptr)
{
    return 0;
}

function getVMRegister($reg)
{
    global $regMap;
    return $regMap[$reg];
}

function setVMRegister($reg, $value)
{
    global $regMap;
    $regMap[$reg] = $value;
}

$opcodes =
[
    0x726574 =>
    [
        'pc = r7',
        function ($arg1, $arg2) use ($regs)
        {
            $regs['pc'] = $regs['r7'];
            return 0;
        }
    ],
    0x69667A =>
    [
        'pc += (reg[$arg1] != 0) ? 1 : $arg2',
        function ($arg1, $arg2) use ($regs)
        {
            $reg = getVMRegister($arg1);
            $regs['pc'] += $reg ? 0x18 : $arg2 * 0x18;
            return 0;
        }
    ],
    0x616464 =>
    [
        'reg[$arg1] += reg[$arg2]',
        function ($arg1, $arg2) use ($regs)
        {
            setVMRegister($arg1, getVMRegister($arg1) + getVMRegister($arg2));
            $regs['pc'] += 0x18;
            return 0;
        }
    ],
    0x633272 =>
    [
        'reg[$arg1] = $arg2',
        function ($arg1, $arg2) use ($regs)
        {
            setVMRegister($arg1, $arg2);
            $regs['pc'] += 0x18;
            return 0;
        }
    ],
    0x6A6D70 =>
    [
        'pc += $arg1',
        function ($arg1, $arg2) use ($regs)
        {
            $regs['pc'] += $arg1 * 0x18;
            return 0;
        }
    ],
    0x723272 =>
    [
        'reg[$arg1] = reg[$arg2]',
        function ($arg1, $arg2) use ($regs)
        {
            setVMRegister($arg1, getVMRegister($arg2));
            $regs['pc'] += 0x18;
            return 0;
        }
    ],
    0x65786974 =>
    [
        'r6 = $arg1, exit from VM',
        function ($arg1, $arg2) use ($regs)
        {
            setVMRegister(0x726573, $arg1);
            return 0;
        }
    ],
    0x737562 =>
    [
        'reg[$arg1] -= reg[$arg2]',
        function ($arg1, $arg2) use ($regs)
        {
            setVMRegister($arg1, getVMRegister($arg1) - getVMRegister($arg2));
            $regs['pc'] += 0x18;
            return 0;
        }
    ],
    0x63616C6C =>
    [
        'r7 = pc + 1, pc += $arg1',
        function ($arg1, $arg2) use ($regs)
        {
            $regs['r7'] = $regs['pc'] + 0x18;
            $regs['pc'] += $arg1 * 0x18;
            return 0;
        }
    ],
    0x6D623272 =>
    [
        'reg[$arg1] = *(byte *)reg[$arg2]',
        function ($arg1, $arg2) use ($regs)
        {
            setVMRegister($arg1, getByte(getVMRegister($arg2)));
            $regs['pc'] += 0x18;
            return 0;
        }
    ],
    0x73686674 =>
    [
        'reg[$arg1] = $arg2 > 0 ? reg[$arg1] >> $arg2 : reg[$arg1] << -$arg2',
        function ($arg1, $arg2) use ($regs)
        {
            $reg = getVMRegister($arg1);
            setVMRegister($arg1, ($arg2 >= 0) ? $reg >> $arg2 : $reg << -$arg2);
            $regs['pc'] += 0x18;
            return 0;
        }
    ],
];

$pc = 0;
foreach ($code as $command)
{
    if (!isset($opcodes[$command[0]]))
    {
        echo "Unknown opcode, PC = $pc\n";
        break;
    }
    $cmd = $opcodes[$command[0]][0];
    $arg1 = $command[1];
    $arg2 = $command[2];

    if (isset($regMap[hexdec(substr($arg1, 2))]))
        $cmd = str_replace('reg[$arg1]', $regMap[hexdec(substr($arg1, 2))], $cmd);
    if (isset($regMap[hexdec(substr($arg2, 2))]))
        $cmd = str_replace('reg[$arg2]', $regMap[hexdec(substr($arg2, 2))], $cmd);

    if (preg_match('/0x0FFFFFFFFFFFFFF([0-9A-F]{1,2})/', $arg1, $matches))
        $arg1 = -(pow(16, strlen($matches[1])) - hexdec($matches[1]));
    if (preg_match('/0x0FFFFFFFFFFFFFF([0-9A-F]{1,2})/', $arg2, $matches))
        $arg2 = -(pow(16, strlen($matches[1])) - hexdec($matches[1]));
    $cmd = str_replace('$arg1', $arg1, $cmd);
    $cmd = str_replace('$arg2', $arg2, $cmd);

    echo '[' . str_pad($pc, 3, '0', STR_PAD_LEFT) . '] ' . $cmd . "\n";
    $pc++;
}


Результат:
Байткод
[000] r3 = 0x1505
[001] r1 = *(byte *)r0
[002] pc += (r1 != 0) ? 1 : 8
[003] r2 = r3
[004] r3 = -5 > 0 ? r3 >> -5 : r3 << --5
[005] r3 += r2
[006] r3 += r1
[007] r2 = 1
[008] r0 += r2
[009] pc += -8
[010] r2 = 0x40E1BAA8FF648029
[011] r3 -= r2
[012] pc += (r3 != 0) ? 1 : 2
[013] r6 = 0, exit from VM
[014] r7 = pc + 1, pc += 0x1F
[015] r5 = r3
[016] r7 = pc + 1, pc += 0x1D
[017] r2 = r5
[018] r2 -= r3
[019] r1 = 0x2A60386296A57940
[020] r2 -= r1
[021] pc += (r2 != 0) ? 1 : 2
[022] r6 = 0, exit from VM
[023] r2 = r3
[024] r2 = 0x20 > 0 ? r2 >> 0x20 : r2 << -0x20
[025] r1 = r3
[026] r1 = -32 > 0 ? r1 >> -32 : r1 << --32
[027] r1 = 0x20 > 0 ? r1 >> 0x20 : r1 << -0x20
[028] r2 -= r1
[029] r0 = 0x3394749A
[030] r2 -= r0
[031] pc += (r2 != 0) ? 1 : 2
[032] r6 = 0, exit from VM
[033] r2 = r3
[034] r2 = -32 > 0 ? r2 >> -32 : r2 << --32
[035] r2 = 0x30 > 0 ? r2 >> 0x30 : r2 << -0x30
[036] r1 = r3
[037] r1 = -48 > 0 ? r1 >> -48 : r1 << --48
[038] r1 = 0x30 > 0 ? r1 >> 0x30 : r1 << -0x30
[039] r2 -= r1
[040] r0 = 0x465E
[041] r2 -= r0
[042] pc += (r2 != 0) ? 1 : 2
[043] r6 = 0, exit from VM
[044] r6 = 1, exit from VM
[045] r3 = 0
[046] r0 = 0
[047] r2 = 0x10
[048] r0 -= r2
[049] pc += (r0 != 0) ? 1 : 2
[050] pc += 2
[051] pc = r7
[052] r0 += r2
[053] r1 = *(byte *)r4
[054] r2 = 0x61
[055] r1 -= r2
[056] pc += (r1 != 0) ? 1 : 2
[057] pc += 8
[058] r3 = -4 > 0 ? r3 >> -4 : r3 << --4
[059] r2 = 0x0A
[060] r3 += r2
[061] r2 = 1
[062] r4 += r2
[063] r0 += r2
[064] pc += -17
[065] r1 = *(byte *)r4
[066] r2 = 0x62
[067] r1 -= r2
[068] pc += (r1 != 0) ? 1 : 2
[069] pc += 8
[070] r3 = -4 > 0 ? r3 >> -4 : r3 << --4
[071] r2 = 0x0B
[072] r3 += r2
[073] r2 = 1
[074] r4 += r2
[075] r0 += r2
[076] pc += -12
[077] r1 = *(byte *)r4
[078] r2 = 0x63
[079] r1 -= r2
[080] pc += (r1 != 0) ? 1 : 2
[081] pc += 8
[082] r3 = -4 > 0 ? r3 >> -4 : r3 << --4
[083] r2 = 0x0C
[084] r3 += r2
[085] r2 = 1
[086] r4 += r2
[087] r0 += r2
[088] pc += -12
[089] r1 = *(byte *)r4
[090] r2 = 0x64
[091] r1 -= r2
[092] pc += (r1 != 0) ? 1 : 2
[093] pc += 8
[094] r3 = -4 > 0 ? r3 >> -4 : r3 << --4
[095] r2 = 0x0D
[096] r3 += r2
[097] r2 = 1
[098] r4 += r2
[099] r0 += r2
[100] pc += -12
[101] r1 = *(byte *)r4
[102] r2 = 0x65
[103] r1 -= r2
[104] pc += (r1 != 0) ? 1 : 2
[105] pc += 8
[106] r3 = -4 > 0 ? r3 >> -4 : r3 << --4
[107] r2 = 0x0E
[108] r3 += r2
[109] r2 = 1
[110] r4 += r2
[111] r0 += r2
[112] pc += -12
[113] r1 = *(byte *)r4
[114] r2 = 0x66
[115] r1 -= r2
[116] pc += (r1 != 0) ? 1 : 2
[117] pc += 8
[118] r3 = -4 > 0 ? r3 >> -4 : r3 << --4
[119] r2 = 0x0F
[120] r3 += r2
[121] r2 = 1
[122] r4 += r2
[123] r0 += r2
[124] pc += -12
[125] r1 = *(byte *)r4
[126] r2 = 0x30
[127] r1 -= r2
[128] pc += (r1 != 0) ? 1 : 2
[129] pc += 8
[130] r3 = -4 > 0 ? r3 >> -4 : r3 << --4
[131] r2 = 0
[132] r3 += r2
[133] r2 = 1
[134] r4 += r2
[135] r0 += r2
[136] pc += -12
[137] r1 = *(byte *)r4
[138] r2 = 0x31
[139] r1 -= r2
[140] pc += (r1 != 0) ? 1 : 2
[141] pc += 8
[142] r3 = -4 > 0 ? r3 >> -4 : r3 << --4
[143] r2 = 1
[144] r3 += r2
[145] r2 = 1
[146] r4 += r2
[147] r0 += r2
[148] pc += -12
[149] r1 = *(byte *)r4
[150] r2 = 0x32
[151] r1 -= r2
[152] pc += (r1 != 0) ? 1 : 2
[153] pc += 8
[154] r3 = -4 > 0 ? r3 >> -4 : r3 << --4
[155] r2 = 2
[156] r3 += r2
[157] r2 = 1
[158] r4 += r2
[159] r0 += r2
[160] pc += -12
[161] r1 = *(byte *)r4
[162] r2 = 0x33
[163] r1 -= r2
[164] pc += (r1 != 0) ? 1 : 2
[165] pc += 8
[166] r3 = -4 > 0 ? r3 >> -4 : r3 << --4
[167] r2 = 3
[168] r3 += r2
[169] r2 = 1
[170] r4 += r2
[171] r0 += r2
[172] pc += -12
[173] r1 = *(byte *)r4
[174] r2 = 0x34
[175] r1 -= r2
[176] pc += (r1 != 0) ? 1 : 2
[177] pc += 8
[178] r3 = -4 > 0 ? r3 >> -4 : r3 << --4
[179] r2 = 4
[180] r3 += r2
[181] r2 = 1
[182] r4 += r2
[183] r0 += r2
[184] pc += -12
[185] r1 = *(byte *)r4
[186] r2 = 0x35
[187] r1 -= r2
[188] pc += (r1 != 0) ? 1 : 2
[189] pc += 8
[190] r3 = -4 > 0 ? r3 >> -4 : r3 << --4
[191] r2 = 5
[192] r3 += r2
[193] r2 = 1
[194] r4 += r2
[195] r0 += r2
[196] pc += -12
[197] r1 = *(byte *)r4
[198] r2 = 0x36
[199] r1 -= r2
[200] pc += (r1 != 0) ? 1 : 2
[201] pc += 8
[202] r3 = -4 > 0 ? r3 >> -4 : r3 << --4
[203] r2 = 6
[204] r3 += r2
[205] r2 = 1
[206] r4 += r2
[207] r0 += r2
[208] pc += -12
[209] r1 = *(byte *)r4
[210] r2 = 0x37
[211] r1 -= r2
[212] pc += (r1 != 0) ? 1 : 2
[213] pc += 8
[214] r3 = -4 > 0 ? r3 >> -4 : r3 << --4
[215] r2 = 7
[216] r3 += r2
[217] r2 = 1
[218] r4 += r2
[219] r0 += r2
[220] pc += -12
[221] r1 = *(byte *)r4
[222] r2 = 0x38
[223] r1 -= r2
[224] pc += (r1 != 0) ? 1 : 2
[225] pc += 8
[226] r3 = -4 > 0 ? r3 >> -4 : r3 << --4
[227] r2 = 8
[228] r3 += r2
[229] r2 = 1
[230] r4 += r2
[231] r0 += r2
[232] pc += -12
[233] r1 = *(byte *)r4
[234] r2 = 0x39
[235] r1 -= r2
[236] pc += (r1 != 0) ? 1 : 2
[237] pc += 8
[238] r3 = -4 > 0 ? r3 >> -4 : r3 << --4
[239] r2 = 9
[240] r3 += r2
[241] r2 = 1
[242] r4 += r2
[243] r0 += r2
[244] pc += -12
[245] pc = r7 



Причёсанный код:
Вменяемый байт-код
r0 = r4 = password
r3 = 0x1505
while (r1 = *(byte *)r0)
  r3 = (r3 << 5) + r3 + r1
  r0++;
if (r3 != 0x40E1BAA8FF648029) return 0;

function 45
r5 = r3
function 45
if (r5 - r3 != 0x2A60386296A57940) return 0;
r2 = (r3 >> 32) - (r3 << 32) >> 32  # r2 = r3 [4..7] - r3 [0..3]
if (r2 != 0x3394749A) return 0;
r2 = (r3 << 32) >> 48 # r2 = r3 [2..3]
r1 = (r3 << 48) >> 48 # r1 = r3 [0..1]
return (r2 - r1 == 0x465E)

function 45:
  r3 = 0, r0 = 0
  while (r0 != 0x10)
    r1 = *(byte *)r4
    if (r1 >= 0x61 && t1 <= 0x66)
      r3 = r3 << 4 + (0x0A + (r1 - 0x61))
      r4++, r0++
      continue;
    if (r1 >= 0x30 && r1 <= 0x39)
      r3 = r3 << 4 + (r1 - 0x30)
      r4++, r0++
      continue



Кейген:
Скрытый текст
for i in range(0, 65536):
  word2 = (0x465E + i) & 0xFFFF
  dword1 = (word2 << 16) + i
  dword2 = (dword1 + 0x3394749A) & 0xFFFFFFFF
  qword2 = (dword2 << 32) + dword1
  qword1 = (qword2 + 0x2A60386296A57940) & 0xFFFFFFFFFFFFFFFF
  str = format(qword1, 'x') + format(qword2, 'x')
#  print hex(i) + ': ' + str
  r3 = 0x1505
  for c in str:
    r3 = ((r3 << 5) + r3 + ord(c)) & 0xFFFFFFFFFFFFFFFF
  if r3 == 0x40E1BAA8FF648029:
    print str
    break

Спасибо! Будем знать!
А как? У меня отказывается. Говорит, надо открывать в 64-битной версии Иды, а самой 64-битной версии там нет.
Ну ок, нельзя.
Ну вот… А я уж было возрадовался, что просто чего-то не заметил… :-(
>> для анализа полученного дампа было бы очень удобно использовать дизассемблер, подобный IDA
www.hopperapp.com
Спасибо!
Извините, где само задание-то? Интересно потренироваться.
Спасибо! Все задание — это сам файл, без пояснений?
Затаив дыхание, я поднимался по чугунной лестнице. Принято считать, что если, поднимаясь по лестнице Ротонды, закрыть глаза, то никогда не дойдешь до конца… Всё это, конечно, сказки, но атмосфера загадочности здесь действительно будто бы витала в воздухе. Я любил подняться до ротондовского тупичка, своего рода, лестничной площадки, и сидеть там, поворачиваясь так и сяк – вдруг и правда удастся увидеть тень от несуществующей, седьмой колонны?

Похоже, не так давно кто-то уже успел здесь побывать… На площадке лежала дискета. Не валялась, а именно лежала, чистая – ни пылинки! Как будто кто-то незадолго до моего прихода ее здесь бережно положил. Почему-то я сразу вспомнил незнакомца в черном. Брать чужие вещи, конечно, нельзя, но я как чувствовал: мне надо знать, что на этой дискете!

Дома, едва скинув куртку и ботинки, я уселся за компьютер. Скачивание и настройка эмулятора флоппи-дисковода заняли минут 15, и вот передо мной уже образ дискеты…
Весьма благодарен.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий