Сейчас на форуме: -Sanchez- (+9 невидимых)

 eXeL@B —› Основной форум —› Реверсинг. Как обратить алгоритм.
. 1 . 2 . 3 . >>
Посл.ответ Сообщение


Ранг: 253.5 (наставник), 684thx
Активность: 0.260.25
Статус: Участник
radical

Создано: 07 января 2019 01:09
· Личное сообщение · #1

Приветствую.
Буду благодарен за помощь в реверсе алго:
Code:
  1. MOV EBX,0xF1A05693
  2. MOV EAX, MYNUMBER  
  3. MOV ECX,COUNT
  4.  
  5. @L_4_00000001:
  6.   ADD EAX,EBX
  7.   MOV EDX,EBX
  8.   MOV DX,AX
  9.   ROL EDX,0x10
  10.   ADD EAX,EDX
  11.   XCHG EAX,EBX
  12.   DEC ECX
  13.   JNZ SHORT @L_4_00000001


В eax результат, задача - восстановить MYNUMBER

-----
ds





Ранг: 90.1 (постоянный), 89thx
Активность: 0.290.56
Статус: Участник

Создано: 07 января 2019 01:46 · Поправил: Boostyq
· Личное сообщение · #2

На си примерно такое
Code:
  1. key = 0xF1A05693;
  2. res = my_number;
  3. itr = count;
  4. do
  5. {
  6.          cur = res;
  7.          res = key;
  8.          key = cur + key + ROTL32((key & 0xFFFF0000) | (cur & 0x0000FFFF), 16);
  9. }
  10. while (--itr > 0);

Нет уверенности что можно решить не зная ebx перед выходом, похоже на какой-то простой хэш

-----
В облачке многоточия


| Сообщение посчитали полезным: f13nd

Ранг: 369.8 (мудрец), 400thx
Активность: 0.390
Статус: Участник

Создано: 07 января 2019 01:59
· Личное сообщение · #3

Код на си. Функция по всей видимости необратима. Поставил для проверки шифровать все числа от 0 до FFFFFFFF, проверю нет ли коллизий. А они должны быть.

Code:
  1. uint32_t encrypt_x(uint32_t eax)
  2. {
  3.          uint32_t count = 5;
  4.          uint32_t ebx = 0xF1A05693;
  5.  
  6.          do {
  7.                  eax = eax + ebx;
  8.                  eax = eax + _rotl(((eax & 0xFFFF) | (ebx & 0xFFFF0000)), 0x10);
  9.                  std::swap(eax, ebx);
  10.          } while (--count);
  11.  
  12.          return eax;
  13. }


-----
PGP key <0x1B6A24550F33E44A>


| Сообщение посчитали полезным: DimitarSerg


Ранг: 253.5 (наставник), 684thx
Активность: 0.260.25
Статус: Участник
radical

Создано: 07 января 2019 02:02
· Личное сообщение · #4

Boostyq пишет:
похоже на какой-то простой хэш

Ну хз хз, "автор как-то генерит" ©

Там в обобщенном варианте считается чексумма от пользовательских данных, назовем dw1, он сравнивается с чексуммой серийника dw2, если упустить часть магии над сирийником, то в самом конце процедура выше считает этот dw2 и кол-во выполнений (в моей функе count) ~500млн... и брутить как-то вообще не комильфо.

-----
ds





Ранг: 90.1 (постоянный), 89thx
Активность: 0.290.56
Статус: Участник

Создано: 07 января 2019 02:09 · Поправил: Boostyq
· Личное сообщение · #5

DimitarSerg пишет:
Там в обобщенном варианте считается чексумма от пользовательских данных, назовем dw1, он сравнивается с чексуммой серийника dw2, если упустить часть магии над сирийником, то в самом конце процедура выше считает этот dw2 и кол-во выполнений (в моей функе count) ~500млн... и брутить как-то вообще не комильфо.

Ну так считаецо то в ту же сторону, а не в обратную
Константы в гугле нет, значит выбрана самостоятельно, а скорее всего рандомная, так что должно быть все дырявое

-----
В облачке многоточия




Ранг: 369.8 (мудрец), 400thx
Активность: 0.390
Статус: Участник

Создано: 07 января 2019 02:09 · Поправил: ntldr
· Личное сообщение · #6

Быстро обращать хэш можно по таблице. Автор может держать у себя файлик на 16 гигабайт однажны посчитанный.

Я бы, если б выпускал шаровару, впихнул вообще 40ка битный медленный хэш. Кейген будет весить всего-то 5 терабайт А меньше - никак (при условии хорошей диффузии в цикле, чтобы не линеаризовалось).
Записал идею в блокнотик, подкину кому-нибудь

-----
PGP key <0x1B6A24550F33E44A>


| Сообщение посчитали полезным: LoDS


Ранг: 253.5 (наставник), 684thx
Активность: 0.260.25
Статус: Участник
radical

Создано: 07 января 2019 02:15
· Личное сообщение · #7

Boostyq пишет:
Ну так считаецо то в ту же сторону, а не в обратную

Да, вот только мне из того дворда, что пришел на вход надо еще развернуть серийник, а я даже его пока узнать не могу точнее еще не пробовал... Думал мб обратимо. Щас тоже брут запущу.

-----
ds





Ранг: 271.2 (наставник), 331thx
Активность: 0.321.49
Статус: Участник

Создано: 07 января 2019 02:34 · Поправил: f13nd
· Личное сообщение · #8

Boostyq пишет:
Нет уверенности что можно решить не зная ebx перед выходом

Весь алгоритм - сложения 16битных значений с переносом в соседнее. Если ebx на выходе известен, алгоритм должен разматываться, если значение неизвестно - он необратим.
ntldr пишет:
Быстро обращать хэш можно по таблице. Автор может держать у себя файлик на 16 гигабайт однажны посчитанный.

Тут не только MYNUMBER переменная, но и COUNT. 4*(2^64) байт это не 16 гигабайт.

-----
2 оттенка серого


| Сообщение посчитали полезным: dosprog

Ранг: 42.8 (посетитель), 16thx
Активность: 0.020.06
Статус: Участник

Создано: 07 января 2019 05:15
· Личное сообщение · #9

Так а какой результат в eax ?
я так понял, зная результат и константу, восстановить COUNT и MYNUMBER ?




Ранг: 253.5 (наставник), 684thx
Активность: 0.260.25
Статус: Участник
radical

Создано: 07 января 2019 05:39
· Личное сообщение · #10

bartolomeo пишет:
Так а какой результат в eax ?

В смысле какой результат ? Вопрос не понятен (код выше рабочий, можно свои значения поставить и затестить, даже не компилируя, тупо вставив в ольку/x64dbg плагином multimate assebler).

Count не надо восстанавливать, он точно известен, просто очень большой, в моем случае count = 0x20000000.

Ну вот напр, вход 0x12345678, count = 0x20000000, выхлоп 0xE550AFAF.
Задача: как-то зная 0xE550AFAF и count = 0x20000000 получить 0x12345678

-----
ds


| Сообщение посчитали полезным: bartolomeo


Ранг: 568.2 (!), 464thx
Активность: 0.550.57
Статус: Участник
оптимист

Создано: 07 января 2019 06:04
· Личное сообщение · #11

ntldr пишет:
Быстро обращать хэш можно по таблице

dword по таблице там процессорного времени макс 15 сек))))

-----
Чтобы правильно задать вопрос, нужно знать большую часть ответа. Р.Шекли.




Ранг: 369.8 (мудрец), 400thx
Активность: 0.390
Статус: Участник

Создано: 07 января 2019 07:42 · Поправил: ntldr
· Личное сообщение · #12

Проверка на коллизии показала, что на 4294967296 входных значений приходится 4294443071 выходных. Я сгенерировал файл с полным брутом и посчитал в нём повторяющиеся числа.

Это для всего-лишь count = 3. Функция необратима, 524225 циферок потерялись.

-----
PGP key <0x1B6A24550F33E44A>


| Сообщение посчитали полезным: Vamit


Ранг: 568.2 (!), 464thx
Активность: 0.550.57
Статус: Участник
оптимист

Создано: 07 января 2019 13:05
· Личное сообщение · #13

DimitarSerg пишет:
Там в обобщенном варианте считается чексумма от пользовательских данных, назовем dw1, он сравнивается с чексуммой серийника dw2

с чего ты взял что тебе нужен этот хэшь? сам серийник должен быть привязан к нему, т.е серийник после манипуляций должен прийти 12345678, а хешь может быть привязан к пользователю что бы потом узнать от кого ушла прога.......

-----
Чтобы правильно задать вопрос, нужно знать большую часть ответа. Р.Шекли.





Ранг: 90.1 (постоянный), 89thx
Активность: 0.290.56
Статус: Участник

Создано: 07 января 2019 13:14
· Личное сообщение · #14

ntldr пишет:
Проверка на коллизии показала, что на 4294967296 входных значений приходится 4294443071 выходных. Я сгенерировал файл с полным брутом и посчитал в нём повторяющиеся числа.

Это для всего-лишь count = 3. Функция необратима, 524225 циферок потерялись.

Позвольте поинтересоваться, каким образом это было проделано?
Вы сгенерировали файл, затем отсортировали значения и после сравнили в один проход?

-----
В облачке многоточия




Ранг: 369.8 (мудрец), 400thx
Активность: 0.390
Статус: Участник

Создано: 07 января 2019 13:26
· Личное сообщение · #15

Boostyq пишет:
Вы сгенерировали файл, затем отсортировали значения и после сравнили в один проход?


Code:
  1. int main()
  2. {
  3.          uint32_t i = 0xFFFFFFFF;
  4.          do {
  5.                  i++;
  6.                  uint32_t enc = encrypt_x(i);
  7.                  printf("%08X\n", enc);
  8.          } while (!= 0xFFFFFFFF);
  9.  
  10.     return 0;
  11. }

Запускаю в консоли, перенаправляю вывод в текстовый файл, получаю 40гб файл с 16ти циферными HEX числами в каждой строке. Затем сортировка, дедупликация и подсчёт оставшихся строк своей прогой.

Сделал как проще. По-уму нужно было сформировать в памяти 16ти гигабайтный массив, затем его отсортировать и посчитать повторы.

-----
PGP key <0x1B6A24550F33E44A>


| Сообщение посчитали полезным: Boostyq

Ранг: 431.7 (мудрец), 389thx
Активность: 0.730.32
Статус: Участник

Создано: 07 января 2019 13:46
· Личное сообщение · #16

Никак не обратить - из-за <ROL>.




Ранг: 253.5 (наставник), 684thx
Активность: 0.260.25
Статус: Участник
radical

Создано: 07 января 2019 14:10 · Поправил: DimitarSerg
· Личное сообщение · #17

ClockMan
Каких 15 секунд ? У меня за ночь (7,5 часов) еще не посчиталось 100 000 ибо count конский просто.

ClockMan пишет:
с чего ты взял что тебе нужен этот хэшь?

потому что сравнение примерное такое:
if encrypt_x(somefunc(Name,Company,Other input data)) == encrypt_x(somemagic(SERIAL_NUM)) {OK}
count = 0x20000000 (число изменено специально, но в проге примерно в районе этого).

Я не знаю под какое значение мне SERIALNUM подбирать, так как это значение "хешируется" функцией encrypt_x

Добавлено спустя 1 минуту
dosprog
А ROL здесь при чем ? Ни один бит при ROL не пострадал

-----
ds





Ранг: 90.1 (постоянный), 89thx
Активность: 0.290.56
Статус: Участник

Создано: 07 января 2019 14:12 · Поправил: Boostyq
· Личное сообщение · #18

dosprog пишет:
Никак не обратить - из-за <ROL>.

Code:
  1. mov edx, 0x12345678
  2. rol edx, 16 ; edx=0x56781234
  3.  
  4. mov edx, 0x56781234
  5. ror edx, 16 ; edx=0x12345678

Это же не shl/sal

-----
В облачке многоточия





Ранг: 253.5 (наставник), 684thx
Активность: 0.260.25
Статус: Участник
radical

Создано: 07 января 2019 14:33 · Поправил: DimitarSerg
· Личное сообщение · #19

Может еще эти данные помогут в решении задачи, а то я не все выложил, возможно ввел кого-то в заблуждение:

chkSerial := calcDword(somemath(SERIAL), $1968BEC2);
chkInput := calcDword(somemagic(INPUTDATA),$19687E53);
ifc chkSerial == chkInput then OK

Второй параметр, как вы уже понимаете - COUNT (счетчик итераций).
Вот это реальные данные из проги, chkSerial я считаю, а нужно узнать somemagic(INPUTDATA)

-----
ds




Ранг: 419.0 (мудрец), 647thx
Активность: 0.460.51
Статус: Участник
"Тибериумный реверсинг"

Создано: 07 января 2019 15:02
· Личное сообщение · #20

DimitarSerg пишет:
chkSerial := calcDword(SERIAL, $1968BEC2);
chkInput := calcDword(somemagic(INPUTDATA),$19687E53);

(SERIAL, 0x406F) == somemagic(INPUTDATA)
предположу фигню: может INPUTDATA всего с 0x406F итерациями крутят и потом вычитают/прибавляют из/к SERIAL?!?




Ранг: 253.5 (наставник), 684thx
Активность: 0.260.25
Статус: Участник
radical

Создано: 07 января 2019 15:10
· Личное сообщение · #21

ELF_7719116
Да вот тоже мысли крутятся, не спроста эти числа именно такие (счетчики циклов)... с разницей всего 0x406F

-----
ds




Ранг: 431.7 (мудрец), 389thx
Активность: 0.730.32
Статус: Участник

Создано: 07 января 2019 15:20 · Поправил: dosprog
· Личное сообщение · #22

DimitarSerg пишет:
А ROL здесь при чем ? Ни один бит при ROL не пострадал

Да, пардон, попутал с действием <RCL>



--Добавлено--


chkSerial := calcDword(SERIAL, $1968BEC2);
chkInput := calcDword(somemagic(INPUTDATA),$19687E53);
ifc chkSerial == chkInput then OK


- а нельзя подглядеть EBX на выходе из <calcDword(somemagic(INPUTDATA),$19687E53);> ?

И дальше уж:

f13nd пишет:
Весь алгоритм - сложения 16битных значений с переносом в соседнее. Если ebx на выходе известен, алгоритм должен разматываться, если значение неизвестно - он необратим.







Ранг: 253.5 (наставник), 684thx
Активность: 0.260.25
Статус: Участник
radical

Создано: 07 января 2019 16:27
· Личное сообщение · #23

dosprog пишет:
а нельзя подглядеть EBX на выходе из <calcDword(somemagic(INPUTDATA),$19687E53

Что ? И что оно нам даст, у нас здесь и так все известные, задача свелась к тому, что

calcDword(SERIAL, $1968BEC2) == calcDword(somemagic(INPUTDATA),$19687E53);
еще упростим:
calcDword(SERIAL, $1968BEC2) == calcDword(KNOWN_VALUE,$19687E53);

-----
ds




Ранг: 431.7 (мудрец), 389thx
Активность: 0.730.32
Статус: Участник

Создано: 07 января 2019 16:30 · Поправил: dosprog
· Личное сообщение · #24

DimitarSerg пишет:
еще упростим:
calcDword(SERIAL, $1968BEC2) == calcDword(KNOWN_VALUE,$19687E53);

Ну так похоже, что у них на выходе и EBX тоже должны быть одинаковые.

Хотя, нет, ерунда...


-- Добавлено --
Тогда, если результат функции (EAX) известен, счётчик тоже, - то брутить.
Что и происходит, насколько я понял.





Ранг: 419.0 (мудрец), 647thx
Активность: 0.460.51
Статус: Участник
"Тибериумный реверсинг"

Создано: 07 января 2019 16:54
· Личное сообщение · #25

DimitarSerg пишет:
calcDword(SERIAL, $1968BEC2) == calcDword(KNOWN_VALUE,$19687E53);

ELF_7719116 пишет:
(SERIAL, 0x406F) == somemagic(INPUTDATA)

Если уж фокуситься на этой процедуре encrypt_x, то странность более всего дифферент по count = 0x406F. Тогда между SERIAL и KNOW_VALUE должна быть прямая зависимость для быстрого вычисления. Алго один и тот-же, и пусть он не обратим.
И второе, есть ли зависимость между KEY (0xF1A05693) и количеством итераций count?! Может найдется такой KEY, при 0x406F итерациях?!



Ранг: 431.7 (мудрец), 389thx
Активность: 0.730.32
Статус: Участник

Создано: 07 января 2019 17:02 · Поправил: dosprog
· Личное сообщение · #26

ELF_7719116 пишет:
calcDword(SERIAL, 0x406F) == somemagic(INPUTDATA)


Кстати, логично - как-то же он сам генерирует валидный сериал, который для раздачи

ELF_7719116 пишет:
KEY (0xF1A05693) и количеством итераций count?! Может найдется такой KEY, при 0x406F итерациях?!

Так это же вроде бы константа, ещё и жёстко заданная в коде ..





Ранг: 71.2 (постоянный), 33thx
Активность: 0.050.12
Статус: Участник

Создано: 07 января 2019 17:30
· Личное сообщение · #27

Короче DimitarSerg не умеет составлять ТЗ. Так невнятно объяснить еще уметь надо.



Ранг: 431.7 (мудрец), 389thx
Активность: 0.730.32
Статус: Участник

Создано: 07 января 2019 17:43
· Личное сообщение · #28

Ну, так исчерпывающая формулировка задачи уже часто в себе и ответ содержит.




Ранг: 253.5 (наставник), 684thx
Активность: 0.260.25
Статус: Участник
radical

Создано: 07 января 2019 18:24
· Личное сообщение · #29

kunix
Спасибо, очень полезный коммент, жаль лайки закончились, так бы обязательно лайкнул.

dosprog пишет:
а нельзя подглядеть EBX на выходе

Еще помудрил над этим ... можно , мы ведь сами считаем, кто нам мешает. И в таком случае обратку я написал, напр.
calcDword($12345678,$10000000) = $231E31A1 (ebx = D4B49E5E)

Написанная мною обратная функция
reCalcDword($D4B49E5E,$10000000) , magic:=$231E31A1;

дает мне обратный результат $12345678, но, нам же необходимо найти такое Х, при котором
calcDword(X,$11000000) также даст $231E31A1

-----
ds


| Сообщение посчитали полезным: zd0x

Ранг: 419.0 (мудрец), 647thx
Активность: 0.460.51
Статус: Участник
"Тибериумный реверсинг"

Создано: 07 января 2019 18:30 · Поправил: ELF_7719116
· Личное сообщение · #30

kunix пишет:
Так невнятно объяснить еще уметь надо.

Судя по написанному, ситуация примерно такая: вводим личные данные (имя, фамилия, страна проживания, кличка собачки...), отправляем на сервер - получаем серийник. В проге вычисляется два хеша - от серийника, и от юзерских данных. Для хешей юзается один и тот-же алго, но на входе разное количество итераций (count). В итоге, зная свои личные данные (или соседа по лестничной клекте), сгенерить первый хеш. Затем, с помощью некоторой зависимости установить второй хеш и реверснуть ветку серийника обратно, попробовав его развернуть из хеша. Неясно лично для меня, какик операции выполняются с данными до процедуры хешировния (возможно INPUT_DATA и SERIAL и без хеша имеют прямую математическую зависимость) в двух ветках и возможно ли урезать count для алго хешировния (если он не обратим).


dosprog пишет:
константа, ещё и жёстко заданная в коде

Да, я понял. Мысль заключалась в том, что автор может юзать меньшее количество итераций для одних и тех же входных данных, зная другие константы KEY. Т е. KEY должен быть в прямой зависимости от COUNT.
Недурно бы предыдущие версии проги посмотреть - какие там константы KEY, COUNT, если сам алго не менялся. Может он вообще по остаточному принципу считается - Т.е. дифферент между count подгоняется после основного обсчета серийника.

ADD
DimitarSerg пишет:
calcDword($12345678,$10000000)
calcDword(X,$11000000) также даст $231E31A1

Поверю что KEY, COUNT1, COUNT2 задаются рандомно. Но дифферент (COUNT1-COUNT2) явно из каких-то математических / логических соображений задан.


. 1 . 2 . 3 . >>
 eXeL@B —› Основной форум —› Реверсинг. Как обратить алгоритм.
:: Ваш ответ
Жирный  Курсив  Подчеркнутый  Перечеркнутый  {mpf5}  Код  Вставить ссылку 
:s1: :s2: :s3: :s4: :s5: :s6: :s7: :s8: :s9: :s10: :s11: :s12: :s13: :s14: :s15: :s16:


Максимальный размер аттача: 500KB.
Ваш логин: german1505 » Выход » ЛС
   Для печати Для печати