Комментарии 13
Я пошёл путём статического анализа, после того, как сдампил расшифрованный кусок.
Ну и изредка gdb для проверок того, что всё верно понял (автоматом архитектура не менялась и сыпались ошибки, поэтому через несколько бряков пришлось работать):
Мнемоники инструкций ВМ даже не проверял, работу смотрел непосредственно в хэндлерах. Набросал скрипт который дизассемблит байт-код, даже интерпретатор влепил на всякий случай.
Результат:
Причёсанный код:
Кейген:
Ну и изредка gdb для проверок того, что всё верно понял (автоматом архитектура не менялась и сыпались ошибки, поэтому через несколько бряков пришлось работать):
Скрипт GDB
target remote localhost:1234
display/3i $pc
hbreak *0x04000148
break *0x200318
set arch i386:x86-64
break *0xFFFFF80000204E19 if $rdx == 12*0x18
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
+2
Однако демо- и триальные версии IDA не работают с 64битным кодом.
Работает бесплатная 5.0 https://www.hex-rays.com/products/ida/support/download_freeware.shtml
-2
>> для анализа полученного дампа было бы очень удобно использовать дизассемблер, подобный IDA
www.hopperapp.com
www.hopperapp.com
+3
Извините, где само задание-то? Интересно потренироваться.
0
Спасибо! Все задание — это сам файл, без пояснений?
0
Затаив дыхание, я поднимался по чугунной лестнице. Принято считать, что если, поднимаясь по лестнице Ротонды, закрыть глаза, то никогда не дойдешь до конца… Всё это, конечно, сказки, но атмосфера загадочности здесь действительно будто бы витала в воздухе. Я любил подняться до ротондовского тупичка, своего рода, лестничной площадки, и сидеть там, поворачиваясь так и сяк – вдруг и правда удастся увидеть тень от несуществующей, седьмой колонны?
Похоже, не так давно кто-то уже успел здесь побывать… На площадке лежала дискета. Не валялась, а именно лежала, чистая – ни пылинки! Как будто кто-то незадолго до моего прихода ее здесь бережно положил. Почему-то я сразу вспомнил незнакомца в черном. Брать чужие вещи, конечно, нельзя, но я как чувствовал: мне надо знать, что на этой дискете!
Дома, едва скинув куртку и ботинки, я уселся за компьютер. Скачивание и настройка эмулятора флоппи-дисковода заняли минут 15, и вот передо мной уже образ дискеты…
Похоже, не так давно кто-то уже успел здесь побывать… На площадке лежала дискета. Не валялась, а именно лежала, чистая – ни пылинки! Как будто кто-то незадолго до моего прихода ее здесь бережно положил. Почему-то я сразу вспомнил незнакомца в черном. Брать чужие вещи, конечно, нельзя, но я как чувствовал: мне надо знать, что на этой дискете!
Дома, едва скинув куртку и ботинки, я уселся за компьютер. Скачивание и настройка эмулятора флоппи-дисковода заняли минут 15, и вот передо мной уже образ дискеты…
+1
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Хардкорный олдскул: QEMU и реверс образа флоппика