Twitter ui_metrics ебаный реверс
Реверс инжиниринг для самых маленьких. Просили отреверсить чет очень простое, воть. Я писал эту заметку тварищу, потому она немного.. ебаная.
На картинке выше представлено 3 подхода к решению:
1) Просто вызывать код через консольку и не вникать че там (easy)
2) Юзать имитацию дум например window на основе jsdom (medium)
3) Реверсить и разобраться как же все-таки работает код (hard)
Похуярили
1) И так, я открыл запросеки, увидел следующую хуйню и решил чекнуть че куда.
2) Подошел, взял за руку и сказал твердо и чётко: ctrl+shift+f. Изи.
3) Ставлю бреки на старте функции на прочек, тк у нас жысончег на выходе.
4) Зачек через консоль очка. Вызываем код и смотрим че происходит. Он вертает результаты вычислений. При том, результат всегда одинаковый. Оки, вход найден, осталось понять как оно это делает.
5) Казалось бы, вертает объект с циферками, а в начале они собстна и есть, но хуй там плавал, оно еще и считает чето, тоесть код получается динамический и весь код (ну почти) и есть по сути шифрование. Оки, тогда как жить то блять? Надо чекать дальше.
6) Я просто скопировал весь код нахуй и отправил на http://jsnice.org/, чтобы привести к более читаемому виду. Переменные стали чутка понятнее, да и в целом приятнее смотреть. Посмотрим, сломался ли код или все норм.
7) Создал файлики и подрубил код к html шаблончику, чтоб дебагать код изолированно. Установил див куда вывести текст для сравнения. Вывод в обоих файлах направил на див. Почекаем норм ли работает файл с читаемыми переменными.
Тоесть я в самом начале нашел где оно там ответ дергает и вхучил туда свой кусок кода, чтобы выводить результаты на страничку. Затестил иии..
Вывод одинаковый, код заебок, значит можно реверсить.
8) Начинаем реверсить локал очка фаел
Оно взяло хуйню и вызвало первую функцию.
Судя по коду://создает див
var content = document.createElement("div");
//скрывает его от юзера, чтоб мозгу не ебать эпилептикам
content.setAttribute("style", "display:none;");
//вставляет в конец боди
document.getElementsByTagName("body")[0].appendChild(content);
//тут делает какую-то ебаную магию с входными числами, которую и нужно понять
var object = parse($($($(content, d), a), b), content, 0);
//удаляет нахуй созданный див
content.parentNode.removeChild(content);
//вертает ебаную хуйню
return object;
Окей, давайте тогда разбираться с этой магией
Оно закидывает
content - блок див и цифру входную в функцию $
$(content, d)
потом опять content и другую цифры
$(.., a)
с третьей та же хуйня
$(.., b)
а потом передает обновленный content, старый и 0 в parse
parse($($($(content, d), a), b), content, 0);
как не трудно догадаться, content превращается в огромное дерево вложенных дивов, а parse дергает нужное.
Тоесть $ делает какие-то вычисления, создает дум дерево и пишет их в него. А parse вытягивает назад всю хуйню.
Окей, тогда надо понять как переписать это на нормальный язык, выкинув работу с дум.
function $(elem, value) {
var i = 0;
for (; i < 8; i++) {
var parent = document.createElement («div»);
elem.appendChild (parent);
parent.innerText = value;
if ((value & 1) == 0) {
elem = parent;
}
value = value ≫ 1;
}
return elem;
}
Тут на вход брало числа и делало какую-то хуйню. вопрос, какую?
ну ясен хуй, оно делало 8 итераций, создавало див и вот еще какая-то вот поебень
if ((value & 1) == 0) {
elem = parent;
}
value = value >> 1;
Хорошо, чекаем доку чтобы понять что это за поебень.
Да, эт побитовые операторы. И хуле они тут делают? Число обрабатывается в двоичном виде:
value = value >> 1;
Ну какбэ на самом деле похуй что они делаю, математика обычная.
На строках 17 и 30 стояли логпоинты, которые писали значения. Не трудно догадаться, что значения тут как в дум дереве и це и есть нужные цифры
Фиксанем функцию $, чтоб вертала только нужное, как было в логе.
Тоесть оно засунуло через $ и отредачило, а потом дернуло через parse всю хуйню и далее сложило их рекурсивно и вернуло остаток от деления на 256
Тоесть вместо parse, если у нас норм массив, можем написать
...reduce(function (a, b) { return a + b }, 0) % 256
На выходе получаем простой код
А теперь сюрпрайз. Если пролистать ниже, везде дублируется точно такой же код, название функции только меняется. Тоесть вот це и была браузерная за щит очка.
Можно было бы ну просто взять и запарсить регулярками входные значения, названия переменных и генерить без трабл, я бы так и сделал.
Только вот код оказался динамическим и я прихуел, подумав что фсе, смэрть. Эт ведь каждый раз новые имена переменных, позиции в коде, код постоянно разный.
Но бля, больше то привязок к браузеру нет нахуй. Поэтому я просто подошел, взял за руку и сказал:
Возьми из фул кода все функции, дерни мне их в массив, выкинь их нахуй и поменяй на вызов моей.
Тк в коде встречались и простые функции, добавил условие проверки, чтоб такую хуйню не трогал, только та которая с привязкой к браузеру
Поэтому нам нужно дернуть основную функцию по имени
Для этого я запилил регулярку, чтоб дернуть нейм нашей основной функции
Тк конец нашей функции дефолт хуйня - возврат результата, режем от нейма функции до сюды.
Также собираем наш шаблон кода. После отправляем в эвал и сохраняем результат в переменную.
Режем через split код по имени нашей функции и вытягиваем ее.
Как видно по скрину, я свою функцию сумм добавил к шаблону кода, в области видимости основной её видно
Моя функция сумм заменяет вот такую повторяющуюся хуйню. Тк оно просто дергает нужные значения, пихает их в дум, а потом вытаскивает, а я сразу чекаю какие нужны и делаю расчет.
Кстати, это логпоинт, если кто не знал. Работает как лог
Собираем код и тестим
Лол, не трогал код больше года, а он все еще рабочий..