DeadShot Опубликовано 4 марта, 2017 Поделиться Опубликовано 4 марта, 2017 В общем сижу ломаю голову, над тем как взломать апгрейды соперников в nfs most wanted (2005). Нашел участок кода, где тока 1 раз берутся уровни апгрейдов машины игрока и копируются в стек, во время загрузки миссии. Во время загрузки, дальше из этих уровней (по 4 байта, которые лежат в стеке) вычисляются другие значения (float, не больше 1 и не меньше 0). Если установить 1, у машин полный апгрейд, 0 = никакого апгрейда. Вот запутался в этом коде: speed.exe+277D11 - fld dword ptr [esp+00000088] speed.exe+277D18 - fcomp dword ptr [speed.exe+49096C] { [1.00] } speed.exe+277D1E - mov [esp+78],00000000 { 0 } speed.exe+277D26 - fnstsw ax speed.exe+277D28 - test ah,01 { 1 } speed.exe+277D28 - test ah,01 { 1 } speed.exe+277D2B - jne speed.exe+277D51 speed.exe+277D2D - mov eax,[esp+00000084] Текущее значение (float) лежит в [esp+88]. Если провести инъекцию по замене текущего значения перед адресом speed.exe+27D11, апгрейды машин меняются. Если провести после speed.exe+277D1E, апгрейды не меняются. Причем в стек ничего не добавляется, как показывается в Tracer cheatengine. Вопрос, что здесь происходит? почитал в интернете про эти команды, но так и не понял, где можно менять значение, чтоб повлияло на машины. Требуется, чтоб дальше смотреть куда эти значения присваиваются. Ссылка на комментарий Поделиться на другие сайты Поделиться
Garik66 Опубликовано 4 марта, 2017 Поделиться Опубликовано 4 марта, 2017 2 часа назад, DeadShot сказал: почитал в интернете про эти команды, но так и не понял, где можно менять значение, чтоб повлияло на машины. ты же сам ответил: 2 часа назад, DeadShot сказал: Если провести инъекцию по замене текущего значения перед адресом speed.exe+27D11, апгрейды машин меняются. mov dword ptr [esp+00000088],(float)1 fld dword ptr [esp+00000088] ЗЫ: И кстати. если занопить прыжок: speed.exe+277D2B - jne speed.exe+277D51 например вот таким образом: Скрытый текст [ENABLE] speed.exe+277D2B: db 90 90 90 90 90 90 // только нужно проверить кол-во байт [DISABLE] speed.exe+277D2B: jne speed.exe+277D51 // только нужно проверить кол-во байт то это тоже думаю приведёт к тому же результату. 1 Ссылка на комментарий Поделиться на другие сайты Поделиться
Dison Опубликовано 4 марта, 2017 Поделиться Опубликовано 4 марта, 2017 Лучше бы скриптик скинул быстрее помогли бы тебе Ссылка на комментарий Поделиться на другие сайты Поделиться
Dino Опубликовано 4 марта, 2017 Поделиться Опубликовано 4 марта, 2017 потому что по адресу speed.exe+277D11 происходит загрузка данных в стек арифметического сопроцессора, и уже от туда оперирует ими Ссылка на комментарий Поделиться на другие сайты Поделиться
DeadShot Опубликовано 4 марта, 2017 Автор Поделиться Опубликовано 4 марта, 2017 Garik66, как я полагаю, это общее значение, поэтому менять в этом месте не нужно. Либо нужно найти место, где это значение будет использовано для применения для каждой машины. Если нет, все равно должен же создаться в памяти хоть какой то общий (для всех машин) объект, вместо этого значения в стеке, который через некоторое время загрузки перезапишется другими значениями, не относящимися к апгрейду машин. Чтоб потом, при доступе которому можно было сделать фильтр моя/не моя машина. jne speed.exe+277D51 Если занопить все равно ничего не изменится. хоть с nop, хоть с je, хоть jmp. Дальше идет еще одна такая проверка, на этот раз на 0.01. speed.exe+277D51 - fld dword ptr [esp+00000088] speed.exe+277D58 - fcomp dword ptr [speed.exe+490968] { [0.01] } speed.exe+277D5E - fnstsw ax speed.exe+277D60 - test ah,41 { 65 } speed.exe+277D63 - jne speed.exe+277F68 Если у машины средние апгрейды (0.0 < x < 1.0) продолжается такой код: speed.exe+277D69 - push esi speed.exe+277D6A - mov ecx,ebx speed.exe+277D6C - call speed.exe+5A840 speed.exe+277D71 - push 00 { 0 } speed.exe+277D73 - push 00 { 0 } speed.exe+277D75 - push speed.exe+4A9A64 { ["part_upgrade"] } speed.exe+277D7A - mov ecx,ebx speed.exe+277D7C - call speed.exe+56D40 но если поставить среднее значение в стеке перед этими проверками (0.5, например) и дойдя сюда speed.exe+277D6A поменять значение в стеке на 0.0 или 1.0, эффекта никакого не будет, все так же останется как и было до этих кодов (0.5, например). fld dword ptr [esp+00000088] fcomp dword ptr [speed.exe+490968] { [0.01] } fnstsw ax jne speed.exe+277F68 Dison, Нет никакого скрипта, т.к. с брейкпоинтом игра вылетит, а при подключение узнать что читает этот адрес появляются, куча инструкций, это не обычный адрес в памяти, это адрес в стеке, даже любой push или pop, add/sub esp, x, будет как доступ. Поэтому решил сам найти методом проверки изменения значения после каждого call метода, используя tracer в cheatengine.Dino, в st(0) и st(1)? пробовал после fnstsw ax выталкивать данные и загружать fldz, fld1, эффекта нет. fnstsw ax, меняет значение регистра eax, как, каким образом? Что за магический код такой? как узнать откуда дальше берутся значения, и какие значения. Ссылка на комментарий Поделиться на другие сайты Поделиться
Garik66 Опубликовано 5 марта, 2017 Поделиться Опубликовано 5 марта, 2017 14 часа назад, DeadShot сказал: Garik66, как я полагаю, это общее значение, поэтому менять в этом месте не нужно. Нужно либо фильтровать на этой инструкции, если тебя интересует конкретная машина, либо смотреть выше по коду, откуда берется в esp - начало структуры машины. 14 часа назад, DeadShot сказал: в st(0) и st(1)? пробовал после fnstsw ax выталкивать данные и загружать fldz, fld1, эффекта нет. После fnstsw ax смысла уже нет что-то переписывать. 14 часа назад, DeadShot сказал: fnstsw ax, меняет значение регистра eax, как, каким образом? опкод fnstsw ax, копирует значение из st(0) в память, либо в регистр ax, в твоём случае именно в ax. // не верно - смотри ниже. Ссылка на комментарий Поделиться на другие сайты Поделиться
Dino Опубликовано 5 марта, 2017 Поделиться Опубликовано 5 марта, 2017 1 час назад, Garik66 сказал: Нужно либо фильтровать на этой инструкции, если тебя интересует конкретная машина, либо смотреть выше по коду, откуда берется в esp - начало структуры машины. После fnstsw ax смысла уже нет что-то переписывать. опкод fnstsw ax, копирует значение из st(0) в память, либо в регистр ax, в твоём случае именно в ax. ну не путай человека, пускай вон лучше справку почитает. fnstsw ничего не копирует из st(0) 14 часа назад, DeadShot сказал: Dino, в st(0) и st(1)? пробовал после fnstsw ax выталкивать данные и загружать fldz, fld1, эффекта нет. fnstsw ax, меняет значение регистра eax, как, каким образом? Что за магический код такой? как узнать откуда дальше берутся значения, и какие значения. чего ты хочешь добиться командами fldz, fld1? Чтобы вытолкнуть из st(0) существует команда fstp никакой магии, элементарное не знание основ. Ссылка на комментарий Поделиться на другие сайты Поделиться
Garik66 Опубликовано 5 марта, 2017 Поделиться Опубликовано 5 марта, 2017 2 минуты назад, Dino сказал: ну не путай человека, пускай вон лучше справку почитает. fnstsw ничего не копирует из st(0) Может я не так понял? вот что написано: Скрытый текст Команды fstsw и fnstsw сохраняют текущее значение слова статуса FPU в указанном месте. Операндом-адресатом может быть либо 16 бит в памяти, либо регистр AX. fstsw перед сохранением слова проверяет на подвешенные немаскируемые прерывания, fnstsw этого не делает. Команды fstcw и fnstcw сохраняют текущее значение управляющего слова FPU в указанном месте в памяти. fstcw перед сохранением слова проверяет на подвешенные немаскируемые прерывания, fnstcw этого не делает. fldcw загружает операнд в управляющее слово FPU. Операндом должно быть 16-битное расположение в памяти. Ссылка на комментарий Поделиться на другие сайты Поделиться
Dino Опубликовано 5 марта, 2017 Поделиться Опубликовано 5 марта, 2017 (изменено) 11 минуту назад, Garik66 сказал: Может я не так понял? вот что написано: Скрыть содержимое Команды fstsw и fnstsw сохраняют текущее значение слова статуса FPU в указанном месте. Операндом-адресатом может быть либо 16 бит в памяти, либо регистр AX. fstsw перед сохранением слова проверяет на подвешенные немаскируемые прерывания, fnstsw этого не делает. Команды fstcw и fnstcw сохраняют текущее значение управляющего слова FPU в указанном месте в памяти. fstcw перед сохранением слова проверяет на подвешенные немаскируемые прерывания, fnstcw этого не делает. fldcw загружает операнд в управляющее слово FPU. Операндом должно быть 16-битное расположение в памяти. под "текущее значение слова статуса FPU" подразумевается регистр состояния SR. Ну сам логически порассуждай, как можно число с плавающей точкой в 16 бит уместить Изменено 5 марта, 2017 пользователем Dino Ссылка на комментарий Поделиться на другие сайты Поделиться
Garik66 Опубликовано 5 марта, 2017 Поделиться Опубликовано 5 марта, 2017 1 минуту назад, Dino сказал: под "текущее значение слова статуса FPU" подразумевается регистр состояния SR. Ну сам логически порассуждай, как можно число с плавающей точкой в 16 бит уместить Ну да в два байта не всунем. - ну застыдил. Ссылка на комментарий Поделиться на другие сайты Поделиться
Garik66 Опубликовано 5 марта, 2017 Поделиться Опубликовано 5 марта, 2017 17 час назад, DeadShot сказал: Если занопить все равно ничего не изменится. хоть с nop, хоть с je, хоть jmp. Дальше идет еще одна такая проверка, на этот раз на 0.01. Если правильно занопить Скрытый текст [ENABLE] speed.exe+277D2B: nop nop [DISABLE] speed.exe+277D2B: jne speed.exe+277D51 , то код на следующую проверку никогда не попадёт. Скрытый текст speed.exe+277CE0 - push -01 { 255 } speed.exe+277CE2 - push speed.exe+47AB30 { [8DE090B8] } speed.exe+277CE7 - mov eax,fs:[00000000] { 0 } speed.exe+277CED - push eax speed.exe+277CEE - mov fs:[00000000],esp { 0 } speed.exe+277CF5 - sub esp,68 { 104 } speed.exe+277CF8 - push ebx speed.exe+277CF9 - push esi speed.exe+277CFA - mov esi,[esp+00000080] speed.exe+277D01 - push 00 { 0 } speed.exe+277D03 - push 00 { 0 } speed.exe+277D05 - mov ebx,ecx speed.exe+277D07 - push esi speed.exe+277D08 - mov [esp+14],ebx speed.exe+277D0C - call speed.exe+56CB0 speed.exe+277D11 - fld dword ptr [esp+00000088] speed.exe+277D18 - fcomp dword ptr [speed.exe+49096C] { [1.00] } speed.exe+277D1E - mov [esp+78],00000000 { 0 } speed.exe+277D26 - fnstsw ax speed.exe+277D28 - test ah,01 { 1 } speed.exe+277D2B - nop // ноп прыжка speed.exe+277D2C - nop // ноп прыжка speed.exe+277D2D - mov eax,[esp+00000084] speed.exe+277D34 - push eax speed.exe+277D35 - mov ecx,ebx speed.exe+277D37 - call speed.exe+5A840 speed.exe+277D3C - pop esi speed.exe+277D3D - mov eax,ebx speed.exe+277D3F - pop ebx speed.exe+277D40 - mov ecx,[esp+68] speed.exe+277D44 - mov fs:[00000000],ecx { 0 } speed.exe+277D4B - add esp,74 { 116 } speed.exe+277D4E - ret 000C { 12 } speed.exe+277D51 - fld dword ptr [esp+00000088] // сюда уже не попадём. Ссылка на комментарий Поделиться на другие сайты Поделиться
DeadShot Опубликовано 5 марта, 2017 Автор Поделиться Опубликовано 5 марта, 2017 Снова не то, кроме с "fnstsw ax загружает регистр состояния sr или swr в ax, долго ломал голову как fnstsw может загрузить float значение в ax. На счет fld1, fldz и инструкций выталкивания fstp, я так и делал, выгружал с помощью fstp [_temp] 2 раза, а дальше уже был тест с комбинациями загрузок 0.00 и 1, с помощью fldz и fld1. На счет снова " Если правильно занопить", в данном случае не нужно ничего нопить, и фильтровать на этом месте никак не получится. т.к. этот код выполнится только по одному разу для апгрейдов ОДНОЙ машины. (как я уже писал, полагаю что создается общий шаблон для создания машин, из которого через хрен знает через сколько инструкций создаются все 4 машины, следствием которого является одинаковые характеристики по мощности, либо другой вариант, машины создаются произвольно, но в процессе езды будут выдергиваться данные из этого шаблона, как множители например к стандартным характеристикам машин). + Это значение используется для вычисления другого значения походу, поставил значение 0.23 в [esp+88], дальше в процессе гонки изменил значение адресов содержащие 0.23 на 1 и на 0, эффекта не получил. Ссылка на комментарий Поделиться на другие сайты Поделиться
Dino Опубликовано 6 марта, 2017 Поделиться Опубликовано 6 марта, 2017 15 час назад, DeadShot сказал: Снова не то, кроме с "fnstsw ax загружает регистр состояния sr или swr в ax, долго ломал голову как fnstsw может загрузить float значение в ax. На счет fld1, fldz и инструкций выталкивания fstp, я так и делал, выгружал с помощью fstp [_temp] 2 раза, а дальше уже был тест с комбинациями загрузок 0.00 и 1, с помощью fldz и fld1. ты код то покажешь? Ссылка на комментарий Поделиться на другие сайты Поделиться
DeadShot Опубликовано 6 марта, 2017 Автор Поделиться Опубликовано 6 марта, 2017 Нет, готового кода, постоянно удаляю что не работает (не нужное). Тот участок описывает примерно вот такую логику, а вся запарка с fnstsw ax, просто счетчик: // upgrade_percent = значению в стеке. if(upgrade_percent == 1.0) { //далее работаем с формулами для максимального апгрейда, //поэтому замена значения upgrade_percent не вызывает никакого эффекта. return; } else if(upgrade_percent == 0.0) { //далее работаем с формулами для апгрейда равного 0, //поэтому замена значения upgrade_percent не вызывает никакого эффекта. return; } // если процент апгрейдов средний работаем с формулами для среднего апгрейда, // который будет использовать значение которое лежит на upgrade_percent. // и который должен соответствовать условию 0 < upgrade_percent < 1. // смысл условия в том что походу в некоторых формулах 0 и 1 могут дать одинаковый результат. // а в случае с апгрейдом машин 0 и 1 должны давать разный результат Используя такую инъекцию, обхожу проверку условий (т.к. машина у меня имеет макс.апгрейды), чтоб дойти до требуемой стандартной формулы: [ENABLE] "speed.exe"+277D11: jmp speed.exe+277D69 nop nop [DISABLE] "speed.exe"+277D11: fld dword ptr [esp+00000088] //Alt: db D9 84 24 88 00 00 00 Дальше ставить трейсер на эту точку (ставя перед условиями проверки, попадем сюда тока после овер миллион инструкций, на что не хватит либо оперативки либо нервов на ожидание): speed.exe+277EDD - mov eax,[esp+00000090] // Достаем из стека процент апгрейда speed.exe+277EE4 - lea edx,[esp+40] speed.exe+277EE8 - push edx speed.exe+277EE9 - push eax // Обратно кладем в стек (процент апгрейда будет иметь другой адрес) speed.exe+277EEA - push esi speed.exe+277EEB - lea ecx,[esp+3C] speed.exe+277EEF - push ecx speed.exe+277EF0 - lea edx,[esp+30] speed.exe+277EF4 - push edx speed.exe+277EF5 - call speed.exe+276280 // Вызов формулы Ну и код самой формулы и куда кладется результат: speed.exe+2762DA - fld dword ptr [speed.exe+49096C] { [1.00] } speed.exe+2762E0 - mov ecx,[esp+20] speed.exe+2762E4 - fsub dword ptr [esp+1C] // процент апгрейда speed.exe+2762E8 - mov eax,[ecx+0C] speed.exe+2762EB - test eax,eax speed.exe+2762ED - fmul dword ptr [esp+04] speed.exe+2762F1 - fld dword ptr [esp+08] speed.exe+2762F5 - fmul dword ptr [esp+1C] // процент апгрейда speed.exe+2762F9 - faddp speed.exe+2762FB - fstp dword ptr [esp+1C] ... speed.exe+276311 - mov edx,[esp+1C] speed.exe+276315 - mov [eax],edx При загрузке, к инструкции speed+276315 получают доступ 72 адреса, может и больше. Теперь уже можно подумывать написать фильтр. Если кто тоже хочет покопаться в поиске фильтра "моя/не моя тачка", началось всё отсюда: speed.exe+2F4A07 - mov esi,eax // тут должен лежать адрес структуры (или чего там) текущей машины // апгрейды в 4 байтом значении (0 - нет апгрейда, 1-4 - уровни апгрейдов) // начиная с [esi/eax+78] вроде speed.exe+2F4A16 - repe movsd speed.exe+2F4A09 - mov ecx,00000066 { 102 } speed.exe+2F4A0E - lea edi,[esp+78] speed.exe+2F4A12 - lea eax,[esp+78] speed.exe+2F4A18 - mov [esp+70],eax А тут уже вычисляется float значение, которую называл процентом апгрейда: speed.exe+278B40 - fild dword ptr [esp+3C] speed.exe+278B44 - lea edx,[esp+10] speed.exe+278B48 - fidiv dword ptr [esp+0C] speed.exe+278B4C - fstp dword ptr [esp+3C] 1 Ссылка на комментарий Поделиться на другие сайты Поделиться
DeadShot Опубликовано 7 марта, 2017 Автор Поделиться Опубликовано 7 марта, 2017 Всю (почти) ночь рассматривал код, над тем как сделать фильтр, запарился, даже голова перестала варить. Сделал скрипт для снятия апгрейдов с соперников (с простым фильтром на основе адреса стека), больше ничего не смог придумать, может кому пригодится: define(address,"speed.exe"+277D11) define(bytes,D9 84 24 88 00 00 00) [ENABLE] assert(address,bytes) alloc(newmem,$1000) label(code) label(point) label(return) newmem: point: cmp esp,0019F618 je code mov dword ptr [esp+88],(float)0 code: fld dword ptr [esp+00000088] jmp return address: jmp newmem nop nop return: [DISABLE] address: db bytes // fld dword ptr [esp+00000088] dealloc(newmem) там где cmp esp,0019F618 - 0019F618 это верхушка стека, дело в том, что на этом месте "speed.exe"+277D11-fld dword ptr [esp+00000088] получают доступ два разных адреса стека, первый адрес 7 раз, второй адрес 21 раз, получается такое соотношение. 1 (игрок) * 7 (видов апгрейда) : 3 (соперники) * 7 (видов апгрейда)) = 7:21. (и чего не проверил это 2 дня назад.) Спасибо за подсказки с fnstsw ax . 1 Ссылка на комментарий Поделиться на другие сайты Поделиться
Dino Опубликовано 8 марта, 2017 Поделиться Опубликовано 8 марта, 2017 Вопрос закрыт? Ссылка на комментарий Поделиться на другие сайты Поделиться
Рекомендуемые сообщения