Перейти к содержанию

MasterGH

Ветераны
  • Постов

    2 999
  • Зарегистрирован

  • Победитель дней

    129

Сообщения, опубликованные MasterGH

  1. Одно и то же делают вроде?

    Или это в целях повышения стабильности? Типа, "а вдруг!.."?

    Не одно и тоже. Способ который я привёл рассчитывает указатель каждый раз заново, а твой - только при активации чита. Применять тот или иной способ зависит от кода игры. Посмотри в дизассемблере что у тебя получается при активации чита. Так же советую это делать почаще для версии CE 6.1, т.к. она может неправильно ассемблировать.

    По поводу вылета на "faddp dword [ecx]". У меня вообще эта инструкция не ассемблировалась. Похоже она работает только с регистрами FPU.

  2. Если честно, не очень понял. Адрес же через указатели генерится... и если адрес которым будет оперировать игра не совпадёт с тем с которым планировалось, просто ничего не произойдёт... по моему...

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

    Эм... указатель-то вроде точный... но не делать сравнения, значит просто его туда дописать отдельно? Э... что-то я тут подвис. Там же куча переменных идёт, через xmm0, все разные, для разных адресов...

    А в этом примере получается что любой адрес будет получать то что генерится в ecx

    И кстати, почему ecx?

    Да, писать "отдельно", точнее встраивать новое условие записи в адрес через цепочку указателей в код игры.

    Ну, куча переменных... надо так написать код, чтобы логика кода игры работала так как надо.

    По ecx будет только тот адрес, который задан указателем. xmm0 и eax остаются в своём контексте выполнения кода, т.е. они равны значения без изменения.

    ecx я взял, потому что в него в оригинальном коде будет все равно перезапись из esi. А это значит, что ecx "свободная переменная" для наших действий до оригинального кода.

  3. В какой-то игре случай с добавлением числа с точкой может быть разным и придётся писать инструкции иначе. Мой пример для всех игр не подходит и его нужно менять.

    Попробую написать подробнее.


    push eax //eax = 175.4727812
    fld dword [esp]
    fadd dword [value]
    fstp dword [esp]
    pop eax // eax = eax + 3.4383


    push eax //eax уже предположительно равен 175.4727812 и его помещаем в стек в [esp]
    fld dword [esp] // загружаем в ST0 значение 175.4727812 из стека
    fadd dword [value] // добавляем к ST0 значение [value], меняется ST0
    fstp dword [esp] // перезаписываем значение в стеке c выплёвываем из ST0 уже сумму
    pop eax // eax = eax + 3.4383 // почти аналогично "выплёвываем" из стека сумму в eax

    По поводу твоего примера, лучше не писать цепочку в скрипте типа mov ebx,[[[[[p4dftre.dll+01849C8C]+24]+28]+128]+4] и убрать лишние инструкции. Цепочку лучше так не писать, потому что она рассчитывает один раз и ассемблируется как mov ebx,[адрес]. А адрес в течении игры может быть другим! Может быть вылет из игры. Если есть полная цепочка указателей, то лучше не делать сравнений... И того получаем:

    newmem:
    pushf
    mov ecx,[p4dftre.dll+01849C8C]
    mov ecx,[ecx + 24]
    mov ecx,[ecx + 28]
    mov ecx,[ecx + 128]
    mov ecx,[ecx + 4]
    lea ecx,[ecx + 208] // ecx = [[[[[p4dftre.dll+01849C8C]+24]+28]+128]+4]+208

    fld dword [value]
    faddp dword [ecx]
    movss xmm0,[ecx]

    popf
    mov ecx,esi
    jmp returnhere

    value:
    dd (float)1.0

    Может быть я где-то ошибся поэтому надо проверить в отладке. И ещё если знать работу с XMM-рами, то возможно можно ещё короче написать, т.к. в xmm0 в "младшей" части уже есть значение, к которому надо прибвить value.

  4. Попробуй сделать следующее. Запусти его трейнер чтобы тот уже работал с игрой. Подключись к процессу трейнера procxp.exe. Найди процесс трейнера (или один из нескольких процессов), выдели его и спосмотри в его свойствах строки. Попробуй через ctrl+f ввести строки из предполагаемого скрипта. Например введи "ENABLE"... возможно у тебя получиться увидеть скрипты на CE, если они будут в памяти процесса.

  5. А при замене куска памяти(Injection), если его можно включать и выключать, да и вообще, может произойти крэш?

    Типа, прога обращается к адресу 004F2A12, а инжект в этот момент заменяет адреса с 004F2A00 по 004F2A20(допустим).

    Очень маловероятно что может произойти "крэш" процесса современной игры.

    ...иногда случается крэш без видимой причины. Всё вроде работает, но при установке брейкпомнта и пошаговом выполнении иногда крэшится. Это, кстати, тоже вопрос, в чём может быть причина?Так всё работает идеально, а поставил брейкпоинт, пару циклов(и не обязательно пару, может вообще не вылететь, может вылететь сразу же) вручную запустил(ну в смысле кнопко Run, когда прога на брейкпоинте тормознёт), и крэш.

    Причина скорее в антиотладочной защите. В Cheat Engine есть режим VEH-дебегера в таких случаях. Но против некоторых версий Старфорса не поможет.

    Ну и интересно было бы как добавить к float'ному значению float'ное же.

    А то в eax что-то вроде 175.4727812, и добавть надо, допустим 3.4383

    Читал статьи(где про FPU), но автоассемблер говорит что хрен бы знал чего я от него хочу...

    Если я не ошибся, то где-то так:

    [ENABLE]
    //code from here to '[DISABLE]' will be used to enable the cheat
    alloc(newmem,2048) //2kb should be enough
    label(returnhere)
    label(originalcode)
    label(exit)
    label(value)

    newmem:
    //....
    push eax //eax = 175.4727812
    fld dword [esp]
    fadd dword [value]
    fstp dword [esp]
    pop eax // eax = eax + 3.4383
    originalcode:
    //...
    exit:
    jmp returnhere

    value:
    dd (float)3.4383

    "Test.exe"+556DE:
    jmp newmem
    returnhere:



    [DISABLE]
    "Test.exe"+556DE:
    mov eax,004546C0
    //Alt: db B8 C0 46 45 00

    dealloc(newmem)

  6. Akama, не спешил бы ты с выводами так скоро и при любой возможности. Вот практическое применение.

    Как видно на рисунке указатели были исследованы, а вот как сделать "бесконечное обучение заклинаниям" будет описано ниже благодаря способу о котором идёт речь. Этот способ установил рамки до какого адреса вверх стоит подниматься из call-ов.

    disciples3intro.gif

    Более подробно про то как сделать бесконечное обучение заклинаниям.

    1. Вникаем в суть игры и интерфейс, что не мало важно.

    Во время изучения заклинания происходят следующие действия.

    - В книге заклинаний выбираем заклинание

    - Щёлкаем по кнопке выучить заклинания и только после того как отпустили кнопку ,то вычитается мана и заклинания выучено.

    2. Раз знаем суть процесса, то находим адрес маны и ставим аппаратный бряк на запись.

    3. Ставим бряк на обработку сообщения на WM_MousUp.

    Щелкаем на кнопке заклинаний, прерываемся на адресе работы с сообщением.

    Снимаем бряк с сообщений и отпускает трейс по ретам.

    Возвращаемся в игру.

    Происходит прерывание на бряке маны. Снимаем бряк. Отпускаем игру и тут же находимся на развилке кода, это место можно считать верхнем порогом кода. Т.е. выше него мы дальше не полезем.

    Итак, определили путь.

    disciples3intro.gif

    Начало пути - нажали на кнопку:

    0040657B . E8 A0D0FFFF CALL Disciple.00403620 - будет началом возможно закрученного пути.

    Конец - вычитание маны:

    0065AA15 |. 8910 MOV DWORD PTR [EAX],EDX – конечный путь

    Вновь ставим бряк на запись маны, прерываемся.

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


    006CF6DA |. 75 33 JNZ SHORT Disciple.006CF70F //можно исправить на JMP как это сделал SERGANT
    006CF6DC |. 8B01 MOV EAX,DWORD PTR [ECX]
    006CF6DE |. 6A 00 PUSH 0
    006CF6E0 |. 6A 01 PUSH 1
    006CF6E2 |. 68 A8A47F00 PUSH Disciple.007FA4A8 ; ASCII "Msg_SpellTooMuch"
    006CF6E7 |. 68 FCA17F00 PUSH Disciple.007FA1FC ; ASCII "Msg_HLIngfo"
    006CF6EC |. FF90 58020000 CALL NEAR DWORD PTR [EAX+258]
    006CF6F2 |. 8B0D A478C301 MOV ECX,DWORD PTR [1C378A4]
    006CF6F8 |. 8B11 MOV EDX,DWORD PTR [ECX]
    006CF6FA |. 68 0000803F PUSH 3F800000
    006CF6FF |. 6A 18 PUSH 18
    006CF701 |. FF92 BC040000 CALL NEAR DWORD PTR [EDX+4BC]
    006CF707 |. 5F POP EDI ; 25F89E08
    006CF708 |. 32C0 XOR AL,AL
    006CF70A |. 5D POP EBP ; 25F89E08
    006CF70B |. 83C4 10 ADD ESP,10
    006CF70E |. C3 RET
    006CF70F |> 8B87 74010000 MOV EAX,DWORD PTR [EDI+174]
    006CF715 |. 3B87 30010000 CMP EAX,DWORD PTR [EDI+130]
    006CF71B |. 73 0B JNB SHORT Disciple.006CF728
    006CF71D |. 8B8F 2C010000 MOV ECX,DWORD PTR [EDI+12C]
    006CF723 |. 8D0481 LEA EAX,DWORD PTR [ECX+EAX*4]
    006CF726 |. EB 06 JMP SHORT Disciple.006CF72E
    006CF728 |> 8D87 3C010000 LEA EAX,DWORD PTR [EDI+13C]
    006CF72E |> 8B10 MOV EDX,DWORD PTR [EAX]
    006CF730 |. 53 PUSH EBX
    006CF731 |. 8B1A MOV EBX,DWORD PTR [EDX]
    006CF733 |. E8 18E1FFFF CALL Disciple.006CD850
    006CF738 |. 84C0 TEST AL,AL
    006CF73A |. 74 09 JE SHORT Disciple.006CF745
    006CF73C |. 5B POP EBX ; 25F89E08
    006CF73D |. 5F POP EDI ; 25F89E08
    006CF73E |. 32C0 XOR AL,AL
    006CF740 |. 5D POP EBP ; 25F89E08
    006CF741 |. 83C4 10 ADD ESP,10
    006CF744 |. C3 RET
    006CF745 |> 56 PUSH ESI
    006CF746 |. 8BB7 74010000 MOV ESI,DWORD PTR [EDI+174]
    006CF74C |. 33C9 XOR ECX,ECX
    006CF74E |. 8D5D 04 LEA EBX,DWORD PTR [EBP+4]
    006CF751 |> 3BB7 30010000 /CMP ESI,DWORD PTR [EDI+130]
    006CF757 |. 73 0B |JNB SHORT Disciple.006CF764
    006CF759 |. 8B87 2C010000 |MOV EAX,DWORD PTR [EDI+12C]
    006CF75F |. 8D04B0 |LEA EAX,DWORD PTR [EAX+ESI*4]
    006CF762 |. EB 06 |JMP SHORT Disciple.006CF76A
    006CF764 |> 8D87 3C010000 |LEA EAX,DWORD PTR [EDI+13C]
    006CF76A |> 8B10 |MOV EDX,DWORD PTR [EAX]
    006CF76C |. 3B4A 24 |CMP ECX,DWORD PTR [EDX+24]
    006CF76F |. 0F83 87000000 |JNB Disciple.006CF7FC
    006CF775 |. 3BB7 30010000 |CMP ESI,DWORD PTR [EDI+130]
    006CF77B |. 73 0B |JNB SHORT Disciple.006CF788
    006CF77D |. 8B87 2C010000 |MOV EAX,DWORD PTR [EDI+12C]
    006CF783 |. 8D04B0 |LEA EAX,DWORD PTR [EAX+ESI*4]
    006CF786 |. EB 06 |JMP SHORT Disciple.006CF78E
    006CF788 |> 8D87 3C010000 |LEA EAX,DWORD PTR [EDI+13C]
    006CF78E |> 8B00 |MOV EAX,DWORD PTR [EAX]
    006CF790 |. 8B50 24 |MOV EDX,DWORD PTR [EAX+24]
    006CF793 |. 83C0 20 |ADD EAX,20
    006CF796 |. 3BCA |CMP ECX,EDX
    006CF798 |. 73 07 |JNB SHORT Disciple.006CF7A1
    006CF79A |. 8B10 |MOV EDX,DWORD PTR [EAX]
    006CF79C |. 8D048A |LEA EAX,DWORD PTR [EDX+ECX*4]
    006CF79F |. EB 03 |JMP SHORT Disciple.006CF7A4
    006CF7A1 |> 83C0 10 |ADD EAX,10
    006CF7A4 |> 83F9 FF |CMP ECX,-1
    006CF7A7 |. 8B00 |MOV EAX,DWORD PTR [EAX]
    006CF7A9 |. 74 09 |JE SHORT Disciple.006CF7B4
    006CF7AB |. 83F9 08 |CMP ECX,8
    006CF7AE |. 7D 04 |JGE SHORT Disciple.006CF7B4
    006CF7B0 |. 8B13 |MOV EDX,DWORD PTR [EBX]
    006CF7B2 |. EB 03 |JMP SHORT Disciple.006CF7B7
    006CF7B4 |> 83CA FF |OR EDX,FFFFFFFF
    006CF7B7 |> 3BD0 |CMP EDX,EAX
    006CF7B9 |. 7C 06 |JL SHORT Disciple.006CF7C1
    006CF7BB |. 41 |INC ECX
    006CF7BC |. 83C3 0C |ADD EBX,0C
    006CF7BF |.^ EB 90 \JMP SHORT Disciple.006CF751
    006CF7C1 |> 8B0D A478C301 MOV ECX,DWORD PTR [1C378A4]
    006CF7C7 |. 8B01 MOV EAX,DWORD PTR [ECX]
    006CF7C9 |. 6A 00 PUSH 0
    006CF7CB |. 6A 01 PUSH 1
    006CF7CD |. 68 F0A17F00 PUSH Disciple.007FA1F0 ; ASCII "Msg_NoRes"
    006CF7D2 |. 68 FCA17F00 PUSH Disciple.007FA1FC ; ASCII "Msg_HLIngfo"
    006CF7D7 |. FF90 58020000 CALL NEAR DWORD PTR [EAX+258]
    006CF7DD |. 8B0D A478C301 MOV ECX,DWORD PTR [1C378A4]
    006CF7E3 |. 8B11 MOV EDX,DWORD PTR [ECX]
    006CF7E5 |. 68 0000803F PUSH 3F800000
    006CF7EA |. 6A 18 PUSH 18
    006CF7EC |. FF92 BC040000 CALL NEAR DWORD PTR [EDX+4BC]
    006CF7F2 |. 5E POP ESI ; 25F89E08
    006CF7F3 |. 5B POP EBX ; 25F89E08
    006CF7F4 |. 5F POP EDI ; 25F89E08
    006CF7F5 |. 32C0 XOR AL,AL
    006CF7F7 |. 5D POP EBP ; 25F89E08
    006CF7F8 |. 83C4 10 ADD ESP,10
    006CF7FB |. C3 RET
    006CF7FC |> 8B4424 10 MOV EAX,DWORD PTR [ESP+10]
    006CF800 |. 33ED XOR EBP,EBP
    006CF802 |. 33DB XOR EBX,EBX
    006CF804 |> 8B8F 30010000 /MOV ECX,DWORD PTR [EDI+130]
    006CF80A |. 894424 14 |MOV DWORD PTR [ESP+14],EAX
    006CF80E |. 8B87 74010000 |MOV EAX,DWORD PTR [EDI+174]
    006CF814 |. 3BC1 |CMP EAX,ECX
    006CF816 |. 896C24 1C |MOV DWORD PTR [ESP+1C],EBP
    006CF81A |. 73 0B |JNB SHORT Disciple.006CF827
    006CF81C |. 8B8F 2C010000 |MOV ECX,DWORD PTR [EDI+12C]
    006CF822 |. 8D0C81 |LEA ECX,DWORD PTR [ECX+EAX*4]
    006CF825 |. EB 06 |JMP SHORT Disciple.006CF82D
    006CF827 |> 8D8F 3C010000 |LEA ECX,DWORD PTR [EDI+13C]
    006CF82D |> 8B11 |MOV EDX,DWORD PTR [ECX]
    006CF82F |. 3B6A 24 |CMP EBP,DWORD PTR [EDX+24]
    006CF832 |. 0F83 A7000000 |JNB Disciple.006CF8DF
    006CF838 |. 3B87 30010000 |CMP EAX,DWORD PTR [EDI+130]
    006CF83E |. 73 0B |JNB SHORT Disciple.006CF84B
    006CF840 |. 8B8F 2C010000 |MOV ECX,DWORD PTR [EDI+12C]
    006CF846 |. 8D0481 |LEA EAX,DWORD PTR [ECX+EAX*4]
    006CF849 |. EB 06 |JMP SHORT Disciple.006CF851
    006CF84B |> 8D87 3C010000 |LEA EAX,DWORD PTR [EDI+13C]
    006CF851 |> 8B00 |MOV EAX,DWORD PTR [EAX]
    006CF853 |. 8B48 24 |MOV ECX,DWORD PTR [EAX+24]
    006CF856 |. 83C0 20 |ADD EAX,20
    006CF859 |. 3BE9 |CMP EBP,ECX
    006CF85B |. 73 06 |JNB SHORT Disciple.006CF863
    006CF85D |. 8B00 |MOV EAX,DWORD PTR [EAX]
    006CF85F |. 03C3 |ADD EAX,EBX
    006CF861 |. EB 03 |JMP SHORT Disciple.006CF866
    006CF863 |> 83C0 10 |ADD EAX,10
    006CF866 |> 83FB FC |CMP EBX,-4
    006CF869 |. 8B00 |MOV EAX,DWORD PTR [EAX]
    006CF86B |. 74 62 |JE SHORT Disciple.006CF8CF
    006CF86D |. 83FB 20 |CMP EBX,20
    006CF870 |. 7F 5D |JG SHORT Disciple.006CF8CF
    006CF872 |. 8B5424 14 |MOV EDX,DWORD PTR [ESP+14]
    006CF876 |. 8B32 |MOV ESI,DWORD PTR [EDX]
    006CF878 |. 8B5424 10 |MOV EDX,DWORD PTR [ESP+10]
    006CF87C |. 8D4C24 18 |LEA ECX,DWORD PTR [ESP+18]

    006CF880 |. 51 |PUSH ECX
    006CF881 |. 6A 00 |PUSH 0
    006CF883 |. F7D8 |NEG EAX
    006CF885 |. 50 |PUSH EAX
    006CF886 |. 56 |PUSH ESI
    006CF887 |. 52 |PUSH EDX
    006CF888 |. C74424 2C 0000000>|MOV DWORD PTR [ESP+2C],0
    006CF890 |. E8 ABB0F8FF |CALL Disciple.0065A940 ; <<<<<<<<<<<<,, + вышли отсюда и смотрим код вверху

    006CF895 |. 83C4 14 |ADD ESP,14
    006CF898 |. 84C0 |TEST AL,AL
    006CF89A |. 74 33 |JE SHORT Disciple.006CF8CF
    006CF89C |. 8B4424 18 |MOV EAX,DWORD PTR [ESP+18]
    006CF8A0 |. 8B0D A078C301 |MOV ECX,DWORD PTR [1C378A0]
    006CF8A6 |. 8B11 |MOV EDX,DWORD PTR [ECX]
    006CF8A8 |. 6A 00 |PUSH 0
    006CF8AA |. 8D2C40 |LEA EBP,DWORD PTR [EAX+EAX*2]
    006CF8AD |. 8B4424 14 |MOV EAX,DWORD PTR [ESP+14]
    006CF8B1 |. 8B6CA8 04 |MOV EBP,DWORD PTR [EAX+EBP*4+4]
    006CF8B5 |. 8B80 E4000000 |MOV EAX,DWORD PTR [EAX+E4]
    006CF8BB |. 6A 00 |PUSH 0
    006CF8BD |. 55 |PUSH EBP
    006CF8BE |. 56 |PUSH ESI
    006CF8BF |. 50 |PUSH EAX
    006CF8C0 |. 68 F8027F00 |PUSH Disciple.007F02F8 ; ASCII "GetResource"
    006CF8C5 |. FF92 90020000 |CALL NEAR DWORD PTR [EDX+290]
    006CF8CB |. 8B6C24 1C |MOV EBP,DWORD PTR [ESP+1C]
    006CF8CF |> 8B4424 14 |MOV EAX,DWORD PTR [ESP+14]
    006CF8D3 |. 45 |INC EBP
    006CF8D4 |. 83C3 04 |ADD EBX,4
    006CF8D7 |. 83C0 0C |ADD EAX,0C
    006CF8DA |.^ E9 25FFFFFF \JMP Disciple.006CF804
    006CF8DF |> 8B4C24 10 MOV ECX,DWORD PTR [ESP+10]
    006CF8E3 |. 51 PUSH ECX
    006CF8E4 |. 57 PUSH EDI ; Disciple.01C3FF80
    006CF8E5 |. E8 B6FCFFFF CALL Disciple.006CF5A0
    006CF8EA |. A1 A478C301 MOV EAX,DWORD PTR [1C378A4]
    006CF8EF |. 8B90 E0000000 MOV EDX,DWORD PTR [EAX+E0]
    006CF8F5 |. 8990 E4000000 MOV DWORD PTR [EAX+E4],EDX
    006CF8FB |. 8B8F 78010000 MOV ECX,DWORD PTR [EDI+178]
    006CF901 |. 8B97 7C010000 MOV EDX,DWORD PTR [EDI+17C]
    006CF907 |. 8B07 MOV EAX,DWORD PTR [EDI] ; Disciple.007FA410
    006CF909 |. 8BB7 70010000 MOV ESI,DWORD PTR [EDI+170]
    006CF90F |. 8B9F 74010000 MOV EBX,DWORD PTR [EDI+174]
    006CF915 |. 83C4 08 ADD ESP,8
    006CF918 |. 51 PUSH ECX
    006CF919 |. 52 PUSH EDX
    006CF91A |. 8BCF MOV ECX,EDI ; Disciple.01C3FF80
    006CF91C |. FF50 4C CALL NEAR DWORD PTR [EAX+4C]
    006CF91F |. 8B07 MOV EAX,DWORD PTR [EDI] ; Disciple.007FA410
    006CF921 |. 53 PUSH EBX
    006CF922 |. 8BCF MOV ECX,EDI ; Disciple.01C3FF80
    006CF924 |. 89B7 70010000 MOV DWORD PTR [EDI+170],ESI
    006CF92A |. FF50 50 CALL NEAR DWORD PTR [EAX+50]
    006CF92D |. E8 9E060000 CALL Disciple.006CFFD0
    006CF932 |. E8 C9080000 CALL Disciple.006D0200
    006CF937 |. 8B0D A478C301 MOV ECX,DWORD PTR [1C378A4]
    006CF93D |. 85C9 TEST ECX,ECX
    006CF93F |. 74 0F JE SHORT Disciple.006CF950
    006CF941 |. 8B11 MOV EDX,DWORD PTR [ECX]
    006CF943 |. 68 0000803F PUSH 3F800000
    006CF948 |. 6A 06 PUSH 6
    006CF94A |. FF92 BC040000 CALL NEAR DWORD PTR [EDX+4BC]
    006CF950 |> 5E POP ESI ; 25F89E08
    006CF951 |. 5B POP EBX ; 25F89E08
    006CF952 |. 5F POP EDI ; 25F89E08
    006CF953 |. B0 01 MOV AL,1
    006CF955 |. 5D POP EBP ; 25F89E08
    006CF956 |. 83C4 10 ADD ESP,10
    006CF959 \. C3 RET
    006CF6D6  |.  896C24 08 		MOV DWORD PTR [ESP+8],EBP


    {
    int v1; // ebp@1
    int v2; // edi@1
    char result; // al@2
    signed int v4; // ecx@7
    int v5; // ebx@7
    unsigned int v6; // esi@7
    int v7; // eax@9
    int v8; // eax@13
    int v9; // eax@15
    int v10; // eax@16
    signed int v11; // eax@18
    signed int v12; // edx@20
    int v13; // eax@25
    signed int v14; // ebx@25
    unsigned int v15; // ebp@25
    unsigned int v16; // eax@26
    int v17; // ecx@27
    int v18; // eax@31
    int v19; // eax@33
    int v20; // eax@34
    int v21; // eax@36
    int v22; // esi@38
    int v23; // eax@1
    char v24; // zf@1
    int v25; // eax@15
    unsigned int v26; // edx@15
    unsigned int v27; // ecx@26
    int v28; // eax@33
    unsigned int v29; // ecx@33
    int v30; // esi@41
    int v31; // ebx@41
    int v32; // eax@41
    int v33; // [sp+14h] [bp-10h]@1
    int v34; // [sp+18h] [bp-Ch]@26
    unsigned int v35; // [sp+20h] [bp-4h]@26
    int v36; // [sp+1Ch] [bp-8h]@38

    v2 = a1;
    v23 = (*(int (**)(void))(*(_DWORD *)dword_1C378A4 + 0x34))();
    v1 = v23;
    v24 = *(_DWORD *)(dword_1C378A4 + 0xE4) == *(_DWORD *)(dword_1C378A4 + 0xE0); // ключевое место
    v33 = v23;
    if ( v24 )
    {
    (*(int (__stdcall **)(char *, char *, signed int, _DWORD))(*(_DWORD *)dword_1C378A4 + 0x258))(
    "Msg_HLIngfo",
    "Msg_SpellTooMuch",
    1,
    0);
    (*(int (__stdcall **)(signed int, unsigned int))(*(_DWORD *)dword_1C378A4 + 0x4BC))(24, 0x3F800000u);
    result = 0;
    }
    else
    {
    *(_DWORD *)(v2 + 372) >= *(_DWORD *)(v2 + 304);
    if ( (unsigned __int8)sub_6CD850() )
    {
    result = 0;
    }
    else
    {
    v6 = *(_DWORD *)(v2 + 372);
    v4 = 0;
    v5 = v1 + 4;
    while ( 1 )
    {
    if ( v6 >= *(_DWORD *)(v2 + 304) )
    v7 = v2 + 316;
    else
    v7 = *(_DWORD *)(v2 + 0x12C) + 4 * v6;
    if ( (unsigned int)v4 >= *(_DWORD *)(*(_DWORD *)v7 + 0x24) )
    break;
    if ( v6 >= *(_DWORD *)(v2 + 304) )
    v8 = v2 + 316;
    else
    v8 = *(_DWORD *)(v2 + 0x12C) + 4 * v6;
    v25 = *(_DWORD *)v8;
    v26 = *(_DWORD *)(v25 + 0x24);
    v9 = v25 + 32;
    if ( v4 >= v26 )
    v10 = v9 + 16;
    else
    v10 = *(_DWORD *)v9 + 4 * v4;
    v11 = *(_DWORD *)v10;
    if ( v4 == -1 || v4 >= 8 )
    v12 = -1;
    else
    v12 = *(_DWORD *)v5;
    if ( v12 < v11 )
    {
    (*(int (__stdcall **)(char *, char *, signed int, _DWORD))(*(_DWORD *)dword_1C378A4 + 600))(
    "Msg_HLIngfo",
    "Msg_NoRes",
    1,
    0);
    (*(int (__stdcall **)(unsigned int, signed int))(*(_DWORD *)dword_1C378A4 + 0x4BC))(0x18u, 1065353216);
    return 0;
    }
    ++v4;
    v5 += 12;
    }
    v13 = v33;
    v15 = 0;
    v14 = 0;
    while ( 1 )
    {
    v27 = *(_DWORD *)(v2 + 304);
    v34 = v13;
    v16 = *(_DWORD *)(v2 + 372);
    v35 = v15;
    if ( v16 >= v27 )
    v17 = v2 + 316;
    else
    v17 = *(_DWORD *)(v2 + 300) + 4 * v16;
    if ( v15 >= *(_DWORD *)(*(_DWORD *)v17 + 36) )
    break;
    if ( v16 >= *(_DWORD *)(v2 + 304) )
    v18 = v2 + 316;
    else
    v18 = *(_DWORD *)(v2 + 300) + 4 * v16;
    v28 = *(_DWORD *)v18;
    v29 = *(_DWORD *)(v28 + 36);
    v19 = v28 + 32;
    if ( v15 >= v29 )
    v20 = v19 + 16;
    else
    v20 = v14 + *(_DWORD *)v19;
    v21 = *(_DWORD *)v20;
    if ( v14 != -4 )
    {
    if ( v14 <= 32 )
    {
    v22 = *(_DWORD *)v34;
    v36 = 0;
    if ( (unsigned __int8)SFChangeResourceNum(v33, v22, -v21, 0, &v36) )
    {
    (*(int (__stdcall **)(char *, _DWORD, int, _DWORD, _DWORD, _DWORD))(*(_DWORD *)dword_1C378A0 + 656))(
    "GetResource",
    *(_DWORD *)(v33 + 228),
    v22,
    *(_DWORD *)(v33 + 12 * v36 + 4),
    0,
    0);
    v15 = v35;
    }
    }
    }
    ++v15;
    v14 += 4;
    v13 = v34 + 12;
    }
    SFSpellStudent(v2, v33);
    *(_DWORD *)(dword_1C378A4 + 228) = *(_DWORD *)(dword_1C378A4 + 224);
    v30 = *(_DWORD *)(v2 + 368);
    v31 = *(_DWORD *)(v2 + 372);
    (*(int (__thiscall **)(int, _DWORD, _DWORD))(*(_DWORD *)v2 + 76))(
    v2,
    *(_DWORD *)(v2 + 380),
    *(_DWORD *)(v2 + 376));
    v32 = *(_DWORD *)v2;
    *(_DWORD *)(v2 + 368) = v30;
    (*(int (__thiscall **)(int, int))(v32 + 80))(v2, v31);
    sub_6CFFD0();
    sub_6D0200();
    if ( dword_1C378A4 )
    (*(int (__stdcall **)(signed int, unsigned int))(*(_DWORD *)dword_1C378A4 + 1212))(6, 0x3F800000u);
    result = 1;
    }
    }
    return result;
    }
    char __usercall sub_6CF6B0<al>(int a1<eax>)

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

    x1= [[1C378A4]+0xE4] – это значение устанавливается равным [[1C378A4]+0xE0] при изучении заклинания

    x2= [[1C378A4]+0xE0] – количество игровых ходов, т.е. не игрока, а именно ходов игры.

    Если x1 и x2 равны, то нельзя выучить заклинание.

    x1 до начала самого первого хода в игре равно мусору. После изучения первого заклинания на пример на 5-ом ходу когда x2=5, то x1 становится равным 5. Делаем ход x2 становится равным 6, а x1 остаётся равным 3. Изучаем заклинание x1 становится равным 6.

    Вывод: нельзя найти отсеиванием, т.к. врядли додумаешься до правил поиска )

    Про то, как сделать пользование магией будет скоро в следующем посте. Надо делать почти также. Ставить бряк на Ману использовать заклинание и смотреть выше по коду…

    Короче что просил Иван Иванови, то сделал.

    Берём русскую версию CE.

    \"Подсоединяем\" процесс игры

    Идём в отладчик, нажимаем на Автоассемблер.

    Пишем скрипт ниже.

    Связываем, сохраняем таблицу. Активируем и играем.


    //Бесконечное изучение заклинания
    DisciplesIII.exe+2CF6DA:>E40000008BE83B91E0000000896C2408YYxxxxxxxx006A0168A8A47F0068FC
    db eb 33

    //Бесконечное использование заклинания
    DisciplesIII.exe+27BFD7:>006A01508BCDFF92380600008B5C2418YYxxxxxxxx008B85E0000000898388
    db 90 90 90 90 90 90

    //Бесконечная постройка зданий
    DisciplesIII.exe+2F35E3:>2418508BC78BCDE8xxxxxxxx85F67407YYxxxxxxxx00018B0Dxxxxxxxx85C9
    db 90 90 90 90 90 90 90

    [DISABLE]
    DisciplesIII.exe+2CF6DA:>E40000008BE83B91E0000000896C2408YYxxxxxxxx006A0168A8A47F0068FC
    db 75 33

    DisciplesIII.exe+27BFD7:>006A01508BCDFF92380600008B5C2418YYxxxxxxxx908B85E0000000898388
    inc [ebx+0000008c] //ff 83 8c 00 00 00

    DisciplesIII.exe+2F35E3:>2418508BC78BCDE8xxxxxxxx85F67407YYxxxxxxxx90908B0Dxxxxxxxx85C9
    mov byte ptr [esi+000000f0],01 //c6 86 f0 00 00 00 01
    [ENABLE]

    Чит-код на \"Бесконечное использование заклинания\" было сложно найти ) SERGANT, я трейнер делать не буду, так что вся надежда по видимому только на тебя. Если есть вопросы, то я постараюсь помочь.

    Ах да, по водову inc [ebx+0000008c]. Эти данные входят в структуру героя. Если кому надо те могут посмотреть рисунок выше и сравнить с этим указателем [[[[DisciplesIII.exe+18378A4]+00122b24]+1*4]+8c], он же и [ebx+0000008c], где ebx был рассчитан, а 8с = 0x22*4

  7. Это зависит от конкретного случая.

    Надо подразумевать простую схему. Когда используешь этот способ, то у тебя есть два адреса как минимум одного маршрута выполнения машинного кода. Первая точка это бряк на вводе от пользователя, вторая - бряк на адресе параметра, для которого нужно сделать чит. Соответсвенно, если есть проблемы с созданием чита, то нужно исследовать этот маршрут...

  8. MasterGH, в старых версиях было специальное меню под это, где добавлялись функции в трейнер и вешались на них хоткеи. В 6.1 я такого не наблюдаю, либо это меню где-то спрятано...

    В меню "Файл" есть опция генерации трейнера... Какие у тебя могли возникнуть трудности? очень странно

  9. Akama, уже все давно узнали, что есть такая таблица ) И давно решили изучать её или нет...

    Отлавливать функции нажатия клавиш надо для работы в отладке, чтобы определить как код игры реагирует на ввод пользователя. Если интересуют подробности, то их нужно искать в отладке...

  10. В первый раз вижу такое меню. Хоть бы ссылку привёл этого видео.

    D3DWindower помогает не всегда, у нас есть статьи по нему.

    Возможно стоит поискать в Интернете способ установки оконного режима именно для какой-то игры. Если его нет, тогда лесть в отладку. По этому поводу у нас тоже есть статьи.

  11. Вот изменённый вариант:

    post-3-1309711951,56_thumb.png


    Скрипт установки условного брейкпоинта на функции TranslateMessage.

    В параметрах сравнения участвует код сообщения "UINT message"
    Если сообщение равно сравниваемому, то отладчик прервётся и в поле лога выведет параметры структуры MSG

    BOOL TranslateMessage(
    const MSG* lpMsg // Указатель на структуру MSG, которая содержит информацию о сообщении извлеченную из очереди сообщений вызывающего потока при помощи использования функции GetMessage или PeekMessage.
    );

    typedef struct {
    HWND hwnd; // Дескриптор окна, оконная процедура которого принимает сообщение.
    UINT message; // Определяет код сообщения. Приложения могут использовать только младшее слово; старшее слово зарезервировано системой.
    WPARAM wParam; // Определяет дополнительную информацию о сообщении. Точное значение зависит от значения члена структуры message.
    LPARAM lParam; // Определяет дополнительную информацию о сообщении. Точное значение зависит от значения члена структуры message.
    DWORD time; // Определяет время, в которое сообщение было помещено в очередь.
    POINT pt; // Устанавливает позицию курсора, в экранных координатах, в момент, когда сообщение было помещено в очередь.
    } MSG, *PMSG;


    Пример использования.

    Пример1. Установка условного брейкпоинта функции TranslateMessage в сравнении с параметром MSG:
    -- Сработает когда пользователь отпустит левую кнопку мышки

    WM_LBUTTONUP = 0x202 (другие коды сообщени ищите в Интернете)
    StartDebug_TranslateMessageCondition_onMSG(WM_LBUTTONUP)

    Пример2. Установика безусловного брейкпоинта с логировнием всех сообщений:

    StartDebug_TranslateMessage()

    Пример3. Если необходимо только прерваться на некоторой функции без сбора параметров:

    StartDebugSomeFunction(functionName)

    Пример4. Если необоходимо остановить отладку, то вызывать:

    StopDebug()
    ]]--

    local mode = 0
    local addressesBreakPoint = {}
    local countAddressesBreakPoint = 0

    function AddBreakPointExecut(addressFunction)
    countAddressesBreakPoint = table.getn(addressesBreakPoint)
    countAddressesBreakPoint = countAddressesBreakPoint + 1
    addressesBreakPoint[countAddressesBreakPoint] = addressFunction
    debug_setBreakpoint(addressFunction, 1, bptExecute)
    end

    function DeleteAllBreakPoint()
    for i=1, countAddressesBreakPoint do
    debug_removeBreakpoint(addressesBreakPoint[i])
    end
    countAddressesBreakPoint = 0
    end

    -- Единая функция обработки сообщений о прерывании
    function debugger_onBreakpoint()

    local withIn = false
    for i=1, countAddressesBreakPoint do
    if (EIP == addressesBreakPoint[i]) then
    withIn = true
    break
    end
    end

    if (not withIn) then
    return 1
    end

    if ( (mode == 1) or (mode == 2) ) then
    local pMSG = readInteger(ESP+0x4)
    local MSG = readInteger(pMSG+0x4)

    if ((mode == 1) and (MSG ~= _iMSGBreak)) then
    return 1
    end

    local s = string.format(" • Call to %s from \"%s\" •\n\r\n>> hWnd = %X\n\r\n>> MSG = %X\n\r\n>> wParam = %X\n\r\n>> lParam = %08X\n\r\n>> Time = %X\n\r\n>> Point = %i x %i\n\r\n", getNameFromAddress(EIP), getNameFromAddress(readInteger(ESP)),
    readInteger(pMSG),
    MSG,
    readInteger(pMSG+0x8),
    readInteger(pMSG+0xC),
    readInteger(pMSG+0x10),
    readInteger(pMSG+0x14), readInteger(pMSG+0x18))

    if (mode == 1) then -- WM_LBUTTONUP
    print(s) -- записываем в лог LuaEngine текст из loglist
    return 0 -- ставим бряк
    else -- в случае если условие не выполнено
    print(s) -- записываем в лог LuaEngine текст из loglist при не выполненом условии
    return 1 -- продолжаем без бряка
    end
    end

    return 0
    end

    function StartDebug_TranslateMessageCondition_onMSG(iMSGBreak)
    DeleteAllBreakPoint()
    mode = 1
    _iMSGBreak = iMSGBreak
    local addressFunction = getAddress("TranslateMessage")
    AddBreakPointExecut(addressFunction)
    print(string.format("Включен режим остановки на фунции TranslateMessage с условием: MSGBreak == %X",iMSGBreak))
    end

    function StartDebug_TranslateMessage()
    DeleteAllBreakPoint()
    mode = 2
    local addressFunction = getAddress("TranslateMessage")
    AddBreakPointExecut(addressFunction)
    print("Включен режим остановки на фунции TranslateMessage без условий")
    end

    function StartDebugSomeFunction(functionName)
    mode = 0
    local addressFunction = getAddress(functionName)
    AddBreakPointExecut(addressFunction)
    end

    function StopDebug()
    DeleteAllBreakPoint()
    _iMSGBreak = 0
    end
    --[[

    Я запустил функцию StartDebug_TranslateMessage() и StopDebug(), а остальные не запускал и поэтому могут быть ошибки, которых я не заметил.

    Если будет время сделаю форму с кнопками, полями ввода и т.п., а то через консоль неудобно.

  12. Кое-что не совсем правильно. И немного не удобно в том, что нет выбора между остановкой просто на функции и остановкой по равенству кода сообщения... я потом поправлю, сейчас нет времени.

    И на будущее createStringlist() в твоём случае постоянно создаёт новый и новый список. Старый при этом не разрушается и происходит "утечка памяти". Достаточно создать список только один раз. Также лучше пользоваться просто print() я что-то "перенасоветовал". Когда я советовал я забыл, что ты ведёшь логи с остановками в Отладчике для пользователя. В этом случае проще использовать print() c длинной строкой (через string.fortmat)... Ладно, как уже писал, позже поправлю.

  13. Актуально:

    local Function = getAddress("TranslateMessage")

    Для лучшей производительности лучше:

    1) cтроку:

    local Condition = 0x202  -- MSG==202  //WM_LBUTTONUP

    вынести из function debugger_onBreakpoint().

    2) строку :

    if (EIP == Function) then

    заменить на:

     if (EIP ~= Function) then 
    return 1
    end

    3) Возможно лучше использовать объект от Stringlist вместо множественного построчного print(). Метод "strings_getText( твой Stringlist )" может сразу возвратить большую строку лога, которую уже можно обработать через print

    Также помимо кодов сообщений можно логировать и адрес возврата по [esp+0]. А также другую информацию:

    BOOL TranslateMessage(
    const MSG* lpMsg // Указатель на структуру MSG, которая содержит информацию о сообщении извлеченную из очереди сообщений вызывающего потока при помощи использования функции GetMessage или PeekMessage.
    );

    typedef struct {
    HWND hwnd; // Дескриптор окна, оконная процедура которого принимает сообщение.
    UINT message; // Определяет код сообщения. Приложения могут использовать только младшее слово; старшее слово зарезервировано системой.
    WPARAM wParam; // Определяет дополнительную информацию о сообщении. Точное значение зависит от значения члена структуры message.
    LPARAM lParam; // Определяет дополнительную информацию о сообщении. Точное значение зависит от значения члена структуры message.
    DWORD time; // Определяет время, в которое сообщение было помещено в очередь.
    POINT pt; // Устанавливает позицию курсора, в экранных координатах, в момент, когда сообщение было помещено в очередь.
    } MSG, *PMSG;

  14. Ссылка на тему человека Recifense, там же есть файл .CT таблицы.

    В [pGold] есть запись, посмотри внимательно. А вот в [iPlayerID] записи нет, потому что это просто переменная для чтения. В этой переменной идентификатор игрока, он всегда равен единице.

    По поводу того, что Recifense лучше меня... Скорее всего так и есть, т.к. у него большой опыт в нахождении связей между указателями. Скорее всего, он не работает с декомпиляторами. Это только я так заморачиваюсь. Метод у него, скорее всего, такой. Если он не может сделать один чит, то он делает другой и ищет связи между поинтерами в структурах сделанных читов. Т.е. в его случае из Dessect Data окна он не вылазит вообще и наверняка активно пользуется сканером памяти в поиске адресов и указателей в структурах... так же, скорее всего, он часто ставит бряки на адреса указателей. Указатели эти расположены в структурах, где они характерны только для данной структуры. Мне надо было обратить внимание на смещение +0x44 в структуре "Передвижения" и искать связь этого указателя со структурой где расположен адрес золота моего героя. Ведь и адрес золота, и адрес очков хождения должны обязательно принадлежать герою за которого я играю.

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

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

  15. Тебе нужно знать программирование под Windows.

    Нужно знать как работать с WinApi функиями чтения, записи в память. Через чтение можно осуществлять чтение цепочек указателей.

    Нужно знать как изменить блок защиты памяти с защиты чтения на защиту записи, чтобы писать в него без исключений...

    Нужно знать работу с поиском dll-ок и принадлежности их к процессам.

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

    Если будешь писать на C++, то нужно знать как создавать окно и привязывать функцию к этому окну.

    Тебе оно надо? :) Это ещё не все. Тебе надо будет самостоятельно искать примеры или самому написать "правильный инжект в выделенную память".

×
×
  • Создать...

Важная информация

Находясь на нашем сайте, Вы автоматически соглашаетесь соблюдать наши Условия использования.