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

Трейнми на обман количества объектов

Рекомендуемые сообщения

post-3-1278316606,34_thumb.png

TrainMe(hard_1_0).rar

Задание.

Сделать количество объектов равное 10000. При нажатии кнопки на плюс должно стать 10001. Если нажали на минус, то должно быть 10000-1=9999.

 

Это не единственное задание. После того как все задания будут сформулированы и решены, то в этом посте будет описание как заданий так и их решений.

Подсказка и ограничение.

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

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

В создании, тестировании трейнми принимали участие: MasterGH и Xipho.  

 

СЛЕДУЮЩИЕ ЗАДАНИЯ ВЫПОЛНЕНЫ.

Для этого трейнми было 3 задания.

Их можно было делать на любом инструменте. Предпочитаемый CheatEngine.

1.Сделать чит-код добавляющий объекты в количестве до 10000.

При следующем нажатии на кнопу вычитания объектов должно быть 9999 или при нажатии на плюс 10001.

2.Восполнить разрушенный объект при помощи скриптов CE.

Т.е. когда мы нажимаем на кнопку вычитания объектов, то разрушенный объект восполняется одним.

3.Сделать так чтобы при вычитание объектов или при их создании, их количество держалось на отметке не меньше 1000 объектов.

Поскольку последнее задание объединяет первые два, то напишу только последнее.

Скрипт1 - Главный

 

Скрытый текст

/*
Процесс: TrainMe(hard_1_0).exe
Чит-код: Скрипт на восттановление указанного кол-ва объектов
Дата: 7.21.2010
Автор скрипта: MasterGH(c)
Версия CE: Cheat Engine 5.6  RUS (v 2.0)

------------------
На _void_RstObj() делалаем два call-а в места:
1) из кода после добавления объектов
2) из кода после уменьшения объектов

*/
alloc(_newmem,2048)
label(_void_RstObj)
label(_EAX_GetCountObj)
label(_void_AddObject)
label(_void_createobj_eax_)
label(_ex)
label(_loop)
label(_a1)
label(_a2)

registersymbol(_void_RstObj)


_newmem:
//Восстановить кол-во недостающих объектов
_void_RstObj:
   pushf
   push eax
   call _EAX_GetCountObj // возвращает eax = кол-во объектов в данный момент
   push ebx
   mov ebx,#1000
   sub ebx,eax
   mov eax,ebx
   pop ebx
   cmp eax, 0    // eax объектов которых не хватает
   jl short _ex      // переход если объектов которых не хватает меньше нуля
   call _void_createobj_eax_
_ex:
   pop eax
   popf
   ret
  
// добавление кол-во объектов  
_void_createobj_eax_:
_loop:
   pushad
   call _void_AddObject// добавляем объект
   popad
   dec eax
   cmp eax,0
   jg short _loop // пока eax больше нуля
   ret
  
//Добавление 1-го объекта:
_void_AddObject:
   push 4010C0
   push 4
   push 4
   call 0040187c
   add esp,04
   test eax,eax
   je short _a1
   mov [eax],000003e7
   jmp short _a2
_a1:
   xor eax,eax
_a2:
   push edi
   lea edi,[esp+08]
   mov [esp+08],eax
   call 00401280
   add esp,0C
   ret
  
//Получение кол-ва объектов в eax:
_EAX_GetCountObj:
   mov eax,[4045B0]
   sub eax,[4045AC]
   sar eax,2
   ret
    
[DISABLE]
dealloc(_newmem)
unregistersymbol(_void_RstObj)

[ENABLE]

 

Скрипт2

 

Скрытый текст
aobscan(_faddress,a1xxxxxxxx2bxxxxxxxxxxxxxxxxxx8dxxxxxxxxc1xxxxxxffxxxxxxxxxx83) alloc(_newmem,2048) label(_returnhere) label(_originalcode) _newmem: call _void_RstObj _originalcode: mov eax,[4045B0] jmp _returnhere _faddress:    // 0040118D = About+CD jmp _newmem _returnhere: [DISABLE] aobscan(_faddress,2bxxxxxxxxxxxxxxxxxx8dxxxxxxxxc1xxxxxxffxxxxxxxxxx83) _faddress-5: mov eax,[4045B0] dealloc(_newmem) //Alt: db A1 B0 45 40 00


[ENABLE]

 

Скрипт3

 

Скрытый текст
aobscan(_faddress,8bxxxxxxxxxx8bxxxxxxxxxx8bxx2bxxc1xxxx85xx0fxxxxxxxxxx83) alloc(_newmem,2048) label(_returnhere) label(_originalcode) _newmem: call _void_RstObj _originalcode: mov ecx,[4045B0] jmp _returnhere _faddress:    // 00401109 = About+49 jmp _newmem nop _returnhere: [DISABLE] aobscan(_faddress,908bxxxxxxxxxx8bxx2bxxc1xxxx85xx0fxxxxxxxxxx83) _faddress-5: mov ecx,[4045B0] dealloc(_newmem) //Alt: db 8B 0D B0 45 40 00  



[ENABLE]

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

что-то наклевывается, но пока больше ощущения, что я нубас)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Нифига не получается разобраться.....

Понял ток что всё по XORено и вышел на инструкцию

00401297 - 83 c0 08 - add eax,04 если 4 поменять на 8 то при нажитии на + будет в два раза больше прибовляться если 16 32 и тд

Ни как не могу выйти на конструктор

Нужна помощь и пояснения а ещё лучше статья по этому ТренМи!!!!!!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Там ничего не поксорено, нет никакого шифрования. И всё очень довольно просто решается.

Необходимо мыслить логически (эта хоть и сложная, но самая простая задача по объектам). Вам нужно 10000 объектов. Объект создаётся, когда кликаем на кнопку складывания. По кнопке конечно же кликать 10000 раз не следует, но можно циклически выполнить кусок кода конструктора и добавление этого объекта в массив. Этот кусок кода сидит на видном месте и выполняется когда кликаем на кнопку складывания.

В скритах CE можно создать поток который с нужными регистрами циклически выполнит этот кусок кода. Также можно это попробовать сделать на Сишном скрипте CE.

Я написал этот трейнми на VC++2008 с шаблоном vector, который применяется в реальных играх. В этом я точно уверен. Дальше будет ещё сложнее трейнми в котором будет динамическое привидение объекта класса предка к одному из нескольких родительских.... на подобии в игре Снайпер Гхост Варриор. И тогда вы сможете попробовать взломать гранаты уже в реальной игре, потренировавшись на трейнми.

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

почти победил и уменьшается и увеличивается, правда число здоровенное)

snap1ir.jpg

капать нужно вот тут


008910D0 /. 83EC 54 sub esp , 54h
008910D3 |. A1 18408900 mov eax , dword ptr [00894018h]
008910D8 |. 33C4 xor eax , esp
008910DA |. 894424 4C mov dword ptr [esp+4Ch] , eax
008910DE |. 8B4424 5C mov eax , dword ptr [esp+5Ch]
008910E2 |. 2D 10010000 sub eax , 00000110h ; Switch (cases 110..111)
008910E7 |. 56 push esi
008910E8 |. 8B7424 5C mov esi , dword ptr [esp+5Ch]
008910EC |. 57 push edi
008910ED |. 0F84 DF000000 je 008911D2h
008910F3 |. 83E8 01 sub eax , 01h
008910F6 |. 0F85 A3000000 jne 0089119Fh
008910FC |. 0FB74424 68 movzx eax , word ptr [esp+68h] ; Case 111 of switch 008910E2
00891101 |. 83E8 02 sub eax , 02h ; Switch (cases 2..3EA)
00891104 |. 0F84 AA000000 je 008911B4h
0089110A |. 2D E7030000 sub eax , 000003E7h
0089110F |. 74 3A je 0089114Bh
00891111 |. 83E8 01 sub eax , 01h
00891114 |. 0F85 85000000 jne 0089119Fh
0089111A |. 8B0D B0458900 mov ecx , dword ptr [008945B0h] ; Case 3EA of switch 00891101
00891120 |. 8B15 AC458900 mov edx , dword ptr [008945ACh]
00891126 |. 8BC1 mov eax , ecx
00891128 |. 2BC2 sub eax , edx
0089112A C1F8 02 sar eax , 02h
0089112D |. 85C0 test eax , eax
0089112F |. 76 6E jbe 0089119Fh
00891131 |. 83E9 04 sub ecx , 04h
00891134 |. 6A 0A push 0Ah
00891136 |. 890D B0458900 mov dword ptr [008945B0h] , ecx
0089113C |. 6A 20 push 20h
0089113E |. 8D4424 18 lea eax , dword ptr [esp+18h]
00891142 |. 2BCA sub ecx , edx
00891144 |. 50 push eax
00891145 |. C1F9 02 sar ecx , 02h
00891148 |. 51 push ecx
00891149 |. EB 3D jmp 00891188h
0089114B |> 6A 04 push 04h ; Case 3E9 of switch 00891101
0089114D |. E8 0A070000 call 0089185Ch
00891152 |. 83C4 04 add esp , 04h
00891155 |. 85C0 test eax , eax
00891157 |. 74 08 je 00891161h
00891159 |. C700 E7030000 mov dword ptr [eax] , 000003E7h
0089115F |. EB 02 jmp 00891163h
00891161 |> 33C0 xor eax , eax
00891163 |> 8D7C24 0C lea edi , dword ptr [esp+0Ch]
00891167 |. 894424 0C mov dword ptr [esp+0Ch] , eax
0089116B |. E8 F0000000 call 00891260h
00891170 |. A1 B0458900 mov eax , dword ptr [008945B0h]
00891175 |. 2B05 AC458900 sub eax , dword ptr [008945ACh]
0089117B |. 6A 0A push 0Ah
0089117D |. 6A 20 push 20h
0089117F |. 8D5424 18 lea edx , dword ptr [esp+18h]
00891183 |. 52 push edx
00891184 |. C1F8 02 sar eax , 02h
00891187 |. 50 push eax
00891188 |> FF15 54308900 call dword ptr [00893054h] ; MSVCR90._itow_s
0089118E 83C4 10 add esp , 10h
00891191 8D4C24 10 lea ecx , dword ptr [esp+10h]
00891195 |. 51 push ecx ; /Text
00891196 |. 6A FF push FFh ; |ControlID = FFFFFFFF (-1.)
00891198 |. 56 push esi ; |hWnd
00891199 |. FF15 F0308900 call dword ptr [008930F0h] ; \SetDlgItemTextW
0089119F |> 33C0 xor eax , eax ; Default case of switch 00891101
008911A1 |. 5F pop edi
008911A2 |. 5E pop esi
008911A3 |. 8B4C24 4C mov ecx , dword ptr [esp+4Ch]
008911A7 |. 33CC xor ecx , esp
008911A9 |. E8 DC050000 call 0089178Ah
008911AE |. 83C4 54 add esp , 54h
008911B1 |. C2 1000 retn 0010h


Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Копать надо там, а лучше выбрать участок кода, который нужно циклически выполнить.

Приведите скрипт на CE который решает задание    :)  Кто сделает и опишет весь путь взлома, тот получит +3 балла в репутацию. 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Что-то никто не решил задачу, даю ещё подсказки



class Myobj
{
    int _id;
public:
    Myobj(int id){_id=id;}
};

vector <Myobj*> v;

// Обработчик сообщений
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    UNREFERENCED_PARAMETER(lParam);

    int wmId, wmEvent;
    wchar_t istr[32];

    switch (message)
    {
    case WM_INITDIALOG:
        return (INT_PTR)TRUE;

    case WM_COMMAND:
        wmId    = LOWORD(wParam);
        wmEvent = HIWORD(wParam);
        // Разобрать выбор в меню:
        switch (wmId)
        {
        case IDC_BUTTON1:
            v.push_back(new Myobj(999));
            _itow_s(v.size(), istr, 10);
            SetDlgItemText(hDlg,IDC_STATIC2,istr);
            break;
        case IDC_BUTTON2:
            if (v.size()<=0) break;
            v.pop_back();
            _itow_s(v.size(), istr, 10);
            SetDlgItemText(hDlg,IDC_STATIC2,istr );
        break;
            case WM_DESTROY:
            EndDialog(hDlg, LOWORD(wParam));
            return (INT_PTR)FALSE;
        break;
        }
    }
    return (INT_PTR)FALSE;
}

===============================


{
  signed int result; // eax@7
  void *v5; // eax@8
  void *v6; // [sp+4h] [bp-48h]@1
  wchar_t String; // [sp+8h] [bp-44h]@7
  unsigned int v8; // [sp+48h] [bp-4h]@1

  v8 = (unsigned int)&v6 ^ dword_404018;
  if ( a2 == 272 )
  {
    result = 1;
  }
  else
  {
    if ( a2 != 273 )
      return 0;
    if ( a3 != 2 )
    {
      if ( a3 == 1001 )
      {
        v5 = operator new(4u);
        if ( v5 )
          *(_DWORD *)v5 = 999;
        else
          v5 = 0;
        v6 = v5;
        sub_401280();
        itow_s((signed int)(dword_4045B0 - Src) >> 2, &String, 0x20u, 10);
        SetDlgItemTextW(hDlg, -1, &String);
      }
      else
      {
        if ( a3 == 1002 && (signed int)(dword_4045B0 - Src) >> 2 )
        {
          dword_4045B0 = (char *)dword_4045B0 - 4;
          itow_s((signed int)(dword_4045B0 - Src) >> 2, &String, 0x20u, 10);
          SetDlgItemTextW(hDlg, -1, &String);
          return 0;
        }
      }
      return 0;
    }
    EndDialog(hDlg, 2);
    result = 0;
  }
  return result;
}

signed int __stdcall DialogFunc(HWND hDlg, int a2, unsigned __int16 a3, int a4)

==============================


.text:004010C0 DialogFunc      proc near               ; DATA XREF: wWinMain(x,x,x,x)+7o
.text:004010C0
.text:004010C0 var_48          = dword ptr -48h
.text:004010C0 String          = word ptr -44h
.text:004010C0 var_4           = dword ptr -4
.text:004010C0 hDlg            = dword ptr  4
.text:004010C0 arg_4           = dword ptr  8
.text:004010C0 arg_8           = word ptr  0Ch
.text:004010C0
.text:004010C0                 sub     esp, 48h
.text:004010C3                 mov     eax, dword_404018
.text:004010C8                 xor     eax, esp
.text:004010CA                 mov     [esp+48h+var_4], eax
.text:004010CE                 mov     eax, [esp+48h+arg_4]
.text:004010D2                 sub     eax, 110h
.text:004010D7                 push    esi
.text:004010D8                 mov     esi, [esp+4Ch+hDlg]
.text:004010DC                 jz      loc_4011EE
.text:004010E2                 sub     eax, 1
.text:004010E5                 jnz     loc_4011BD
.text:004010EB                 movzx   eax, [esp+4Ch+arg_8]
.text:004010F0                 sub     eax, 2
.text:004010F3                 jz      loc_4011D1
.text:004010F9                 sub     eax, 3E7h
.text:004010FE                 jz      short loc_401167
.text:00401100                 sub     eax, 1
.text:00401103                 jnz     loc_4011BD
.text:00401109                 mov     ecx, dword_4045B0
.text:0040110F                 mov     edx, Src
.text:00401115                 mov     eax, ecx
.text:00401117                 sub     eax, edx
.text:00401119                 sar     eax, 2
.text:0040111C                 test    eax, eax
.text:0040111E                 jbe     loc_4011BD
.text:00401124                 sub     ecx, 4
.text:00401127                 push    0Ah             ; Radix
.text:00401129                 mov     dword_4045B0, ecx
.text:0040112F                 push    20h             ; SizeInWords
.text:00401131                 lea     eax, [esp+54h+String]
.text:00401135                 sub     ecx, edx
.text:00401137                 push    eax             ; DstBuf
.text:00401138                 sar     ecx, 2
.text:0040113B                 push    ecx             ; Val
.text:0040113C                 call    ds:_itow_s
.text:00401142                 add     esp, 10h
.text:00401145                 lea     ecx, [esp+4Ch+String]
.text:00401149                 push    ecx             ; lpString
.text:0040114A                 push    0FFFFFFFFh      ; nIDDlgItem
.text:0040114C                 push    esi             ; hDlg
.text:0040114D                 call    ds:SetDlgItemTextW
.text:00401153                 xor     eax, eax
.text:00401155                 pop     esi
.text:00401156                 mov     ecx, [esp+48h+var_4]
.text:0040115A                 xor     ecx, esp
.text:0040115C                 call    sub_4017AA
.text:00401161                 add     esp, 48h
.text:00401164                 retn    10h
.text:00401167 ; ---------------------------------------------------------------------------
.text:00401167
.text:00401167 loc_401167:                             ; CODE XREF: DialogFunc+3Ej
.text:00401167                 push    4               ; unsigned int
.text:00401169                 call    ??2@YAPAXI@Z    ; operator new(uint)
.text:0040116E                 add     esp, 4
.text:00401171                 test    eax, eax
.text:00401173                 jz      short loc_40117D
.text:00401175                 mov     dword ptr [eax], 3E7h
.text:0040117B                 jmp     short loc_40117F
.text:0040117D ; ---------------------------------------------------------------------------
.text:0040117D
.text:0040117D loc_40117D:                             ; CODE XREF: DialogFunc+B3j
.text:0040117D                 xor     eax, eax
.text:0040117F
.text:0040117F loc_40117F:                             ; CODE XREF: DialogFunc+BBj
.text:0040117F                 push    edi
.text:00401180                 lea     edi, [esp+50h+var_48]
.text:00401184                 mov     [esp+50h+var_48], eax
.text:00401188                 call    sub_401280
.text:0040118D                 mov     eax, dword_4045B0
.text:00401192                 sub     eax, Src
.text:00401198                 push    0Ah             ; Radix
.text:0040119A                 push    20h             ; SizeInWords
.text:0040119C                 lea     edx, [esp+58h+String]
.text:004011A0                 push    edx             ; DstBuf
.text:004011A1                 sar     eax, 2
.text:004011A4                 push    eax             ; Val
.text:004011A5                 call    ds:_itow_s
.text:004011AB                 add     esp, 10h
.text:004011AE                 lea     ecx, [esp+50h+String]
.text:004011B2                 push    ecx             ; lpString
.text:004011B3                 push    0FFFFFFFFh      ; nIDDlgItem
.text:004011B5                 push    esi             ; hDlg
.text:004011B6                 call    ds:SetDlgItemTextW
.text:004011BC                 pop     edi
.text:004011BD
.text:004011BD loc_4011BD:                             ; CODE XREF: DialogFunc+25j
.text:004011BD                                         ; DialogFunc+43j ...
.text:004011BD                 xor     eax, eax
.text:004011BF                 pop     esi
.text:004011C0                 mov     ecx, [esp+48h+var_4]
.text:004011C4                 xor     ecx, esp
.text:004011C6                 call    sub_4017AA
.text:004011CB                 add     esp, 48h
.text:004011CE                 retn    10h
.text:004011D1 ; ---------------------------------------------------------------------------
.text:004011D1
.text:004011D1 loc_4011D1:                             ; CODE XREF: DialogFunc+33j
.text:004011D1                 push    2               ; nResult
.text:004011D3                 push    esi             ; hDlg
.text:004011D4                 call    ds:EndDialog
.text:004011DA                 xor     eax, eax
.text:004011DC                 pop     esi
.text:004011DD                 mov     ecx, [esp+48h+var_4]
.text:004011E1                 xor     ecx, esp
.text:004011E3                 call    sub_4017AA
.text:004011E8                 add     esp, 48h
.text:004011EB                 retn    10h
.text:004011EE ; ---------------------------------------------------------------------------
.text:004011EE
.text:004011EE loc_4011EE:                             ; CODE XREF: DialogFunc+1Cj
.text:004011EE                 mov     ecx, [esp+4Ch+var_4]
.text:004011F2                 pop     esi
.text:004011F3                 xor     ecx, esp
.text:004011F5                 mov     eax, 1
.text:004011FA                 call    sub_4017AA
.text:004011FF                 add     esp, 48h
.text:00401202                 retn    10h
.text:00401202 DialogFunc      endp
.text:00401202
.text:00401202 ; ---------------------------------------------------------------------------
<p>.text:00401205                 align 10h
.text:004010C0 ; BOOL __stdcall DialogFunc(HWND, UINT, WPARAM, LPARAM)

Нужно зациклить:

v.push_back(new Myobj(999));

Также в догонку даю ещё задание.

Когда нажимаем на кнопку уменьшения объектов, то при уменьшении объектов нужно их восполнить.

Т.е. уменьшили на 1, то сделать нужно +1. Сделать на скриптах CE.

Итак два задания.

1. В первом посте. Сделать 10000 объектов при помощи скриптов CE.

2. Восполнить разрушенный объект при помощи скриптов CE.

Т.е. мы нажали активировать чит-код (галочку скрипта) и получаем 10000 объектов. Нажали вторую - объекты не уменьшаются.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Внимание. Решение первой задачи.

Создание 10000 объектов после нажатия на активацию скрипта и нажатия на кнопку создания объекта. Хотя можно было помучить и сделать обновления текста, но посчитал это тратой времени.


alloc(_newmem,1024)
registersymbol(_newmem)
label(_loop)
label(_a1)
label(_a2)
createthread(_newmem)

_newmem:
pushad
pushf
push 4010C0
push 4
_loop:
push 04
call 0040187c
add esp,04
test eax,eax
je short _a1
mov [eax],000003e7
jmp short _a2
_a1:
xor eax,eax
_a2:
push edi
lea edi,[esp+08]
mov [esp+08],eax
call 00401280

add esp,04
inc ebx
cmp ebx,#10000
jne short _loop

add esp,08
popf
popad
call GetCurrentThread
ret

[DISABLE]
dealloc(_newmem)
unregistersymbol(_newmem)
[ENABLE]

Да и отмечу ключевые элементы (над ними пришлось попариться в отладке)

[ENABLE]

alloc(_newmem,1024)

registersymbol(_newmem)

label(_loop)

label(_a1)

label(_a2)

createthread(_newmem)

_newmem:

pushad

pushf

push 4010C0 // подглянул в стек, так нужно

push 4

 _loop:// прототип оригинального кода

push 04

call 0040187c

add esp,04

test eax,eax

je short _a1

mov [eax],000003e7

jmp short _a2

_a1:

xor eax,eax

_a2:

push edi

lea edi,[esp+08]

mov [esp+08],eax

call 00401280

add esp,04 // эта фишка обязательно, смотреть стек

inc ebx

cmp ebx,#10000

jne short _loop

add esp,08 // режем стек

popf

popad

 call GetCurrentThread // выходим из потока

ret

[DISABLE]

dealloc(_newmem)

unregistersymbol(_newmem)

Создавая этот скрипт я обратил внимание, что нужно восполнить данные в стеке и вовремя их отсекать. pushad и pushf оставил специально для подстраховки и вы так делайте (действительно ли они там нужны).

Ну и в конце после проверок и вырезания ненужных инстуркций получил:


alloc(_newmem,1024)
registersymbol(_newmem)
label(_loop)
label(_a1)
label(_a2)
createthread(_newmem)

_newmem:
push 4010C0
push 4
_loop:
push 04
call 0040187c
add esp,04
test eax,eax
je short _a1
mov [eax],000003e7
jmp short _a2
_a1:
xor eax,eax
_a2:
push edi
lea edi,[esp+08]
mov [esp+08],eax
call 00401280

add esp,04
inc ebx
cmp ebx,#10000
jne short _loop

add esp,08
ret

[DISABLE]
dealloc(_newmem)
unregistersymbol(_newmem)
[ENABLE]

Решение второй задачи будет и пока остаётся за вами. У вас уже есть пример решения первой задачи. Вот теперь попробуйте решить вторую. Затем будет трейнми2 который я сделаю по предполагаемому коду из реальной игры. 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Убери под спойлер (не прочел решение). Со времени моего первого поста тут, совсем не было времени ковырять, ибо ремонт. А охота добить полностью.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Второе решение оставляю за вами.

Следующее задание - задание3

На примере двух предыдущих решений делаем общий чит-код создающий 1000 объектов, которые не будут уменьшаться. С учётом того, что объекты могут уменьшаться от внешнего влияния (которого в трейнми нет). Это условие характерно, когда в играх начинается новый уровень и объекты создаются с новым уровнем в меньшем количестве.

Подсказки:

1) Внедрить прыг в код трейнми создания объектов на функцию1(1000)

2) Внедрить прыг в код трейнми уменьшения объектов на функцию1(1000)

Функция1 (int a) //количество гранат

{

1) a1= Подсчитать количество гранат

2) a2= a-a1;     // Вычислить недостатающее количество

3) функция2(a2);   // Создать недостающее кол-во гранат

}

функция2 (int a){}

Попробуйте сделать это решение как через автоассемблер так и через C-script.

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Решение 3-го задания (которое объединяет решения первого и второго) имеет следующий вид.

Скрипт1 - Главный


/*
Процесс: TrainMe(hard_1_0).exe
Чит-код: Скрипт на восттановление указанного кол-ва объектов
Дата: 7.21.2010
Автор скрипта: MasterGH(c)
Версия CE: Cheat Engine 5.6  RUS (v 2.0)

------------------
На _void_RstObj() делалаем два call-а в места:
1) из кода после добавления объектов
2) из кода после уменьшения объектов

*/
alloc(_newmem,2048)
label(_void_RstObj)
label(_EAX_GetCountObj)
label(_void_AddObject)
label(_void_createobj_eax_)
label(_ex)
label(_loop)
label(_a1)
label(_a2)

registersymbol(_void_RstObj)


_newmem:
//Восстановить кол-во недостающих объектов
_void_RstObj:
  pushf
  push eax
  call _EAX_GetCountObj // возвращает eax = кол-во объектов в данный момент
  push ebx
  mov ebx,#1000
  sub ebx,eax
  mov eax,ebx
  pop ebx
  cmp eax, 0    // eax объектов которых не хватает
  jl short _ex      // переход если объектов которых не хватает меньше нуля
  call _void_createobj_eax_
_ex:
  pop eax
  popf
  ret
  
// добавление кол-во объектов  
_void_createobj_eax_:
_loop:
  pushad
  call _void_AddObject// добавляем объект
  popad
  dec eax
  cmp eax,0
  jg short _loop // пока eax больше нуля
  ret
  
 //Добавление одного объекта:
_void_AddObject:
  push 4010C0
  push 4
  push 4
  call 0040187c
  add esp,04
  test eax,eax
  je short _a1
  mov [eax],000003e7
  jmp short _a2
_a1:
  xor eax,eax
_a2:
  push edi
  lea edi,[esp+08]
  mov [esp+08],eax
  call 00401280
  add esp,0C
  ret
  
//Получение кол-ва объектов в eax:
_EAX_GetCountObj:
  mov eax,[4045B0]
  sub eax,[4045AC]
  sar eax,2
  ret
  
[DISABLE]
dealloc(_newmem)
unregistersymbol(_void_RstObj)
[ENABLE]

Скрипт2


aobscan(_faddress,a1xxxxxxxx2bxxxxxxxxxxxxxxxxxx8dxxxxxxxxc1xxxxxxffxxxxxxxxxx83)
alloc(_newmem,2048)
label(_returnhere)
label(_originalcode)

_newmem:
call _void_RstObj
_originalcode:
mov eax,[4045B0]
jmp _returnhere

_faddress:    // 0040118D = About+CD
jmp _newmem
_returnhere:

[DISABLE]
aobscan(_faddress,2bxxxxxxxxxxxxxxxxxx8dxxxxxxxxc1xxxxxxffxxxxxxxxxx83)

_faddress-5:
mov eax,[4045B0]

dealloc(_newmem)
//Alt: db A1 B0 45 40 00
[ENABLE]

Скрипт3


aobscan(_faddress,8bxxxxxxxxxx8bxxxxxxxxxx8bxx2bxxc1xxxx85xx0fxxxxxxxxxx83)
alloc(_newmem,2048)
label(_returnhere)
label(_originalcode)

_newmem:
call _void_RstObj
_originalcode:
mov ecx,[4045B0]
jmp _returnhere

_faddress:    // 00401109 = About+49
jmp _newmem
nop
_returnhere:

[DISABLE]
aobscan(_faddress,908bxxxxxxxxxx8bxx2bxxc1xxxx85xx0fxxxxxxxxxx83)

_faddress-5:
mov ecx,[4045B0]

dealloc(_newmem)
//Alt: db 8B 0D B0 45 40 00
[ENABLE]

Изучил я скрипты на С-коде в CheatEngine и в MHS. К сожалению, обе программы не поддерживают ассемблерные вставки в C-коде. В связи с чем, как мне показалось, лучше писать автоассемблерскими скриптами, как я написал выше. Конечно, все три скрипта лучше объединить в один, но задача в целом уже решена   8-)

Спасибо всем, кто принимал участие в решение этого очень сложного трейнми. Если я сделаю ещё трейнми, то уже в отдельной в новой теме.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

ЗдОрово! Сейчас будем учиться!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вставлю свои 5 копеек=) Добавляет недостающих объектов до 10000 и не дает удалять, если объектов меньше тех же 10000.

 

Скрытый текст

[ENABLE]
alloc(obj_add, $1000)
label(delete)
label(exit)
label(exit2)


obj_add:
  mov eax,#10000
  sub eax,dword ptr [esp]
  cmp eax,0
  jl @f
  add esp,14
  jmp TrainMe(hard_1_0).exe+1167
@@:
  add esp,10
  lea ecx,[esp+0C]
  jmp exit

delete:
  cmp eax,#10000
  jbe TrainMe(hard_1_0).exe+11BD
  jmp exit2

TrainMe(hard_1_0).exe+111C:
  jmp delete
  db 90 90 90
exit2:

TrainMe(hard_1_0).exe+11AB:
  jmp obj_add
  db 90 90
exit:

[DISABLE]
TrainMe(hard_1_0).exe+111C:
  test eax,eax
  jbe TrainMe(hard_1_0).exe+11BD

TrainMe(hard_1_0).exe+11AB:
  add esp,10
  lea ecx,[esp+0C]

dealloc(obj_add)

 

  • Плюс 2

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ура, я наконец-то разобрался с данным TrainMe.

Дополнил решение комментариями, чтобы тем кто пробует решить было проще разобраться.

Так же я "заморочился" и добавил обновление надписи, так что все опции влияют сразу и сразу видно изменение.

 

Ссылка на скачивание таблицы: https://yadi.sk/d/rCgbzaXO3AgAf4

 

Функции по пунктам:

0. Основные функции:

Spoiler

[ENABLE]
// функция апдейта надписи
globalalloc(update_label, 2048)
// функция получения текущего количества объектов
globalalloc(get_count, 2048)
// функция добавления одного объекта
globalalloc(create_object, 2048)

// здесь будем хранить число строкой
globalalloc(update_label_buffer, 32)


update_label:
// принимает один параметр - число
mov eax,[esp+4]

// передаваемые парметры:
// - десятичная система счисления
// - размер буффера - 32 байта
// - ссылка на буфер
// - собственно число
push #10
push #32
push update_label_buffer
push eax
// собственно зовем функцию преобразования
call dword ptr [TrainMe(hard_1_0).exe+30B8] { ->MSVCR90.itow_s }
// поухаживаем за ленивой функцией и сдвинем стек за нее >.>
add esp,10

// берем handle окна
// выдрал из ESI при вычитании
mov eax,[uxtheme.dll+50C5C]

// передаваемые параметры
// - наша строка с числом
// - ID надписи
// - хендл окна
push update_label_buffer
push -1
push eax
call dword ptr [TrainMe(hard_1_0).exe+30F0] { ->USER32.SetDlgItemTextW }
// это хорошая функция, она сама почистила стек за собой

// принимали один dword, значит и удаляем один dword из стека при выходе
ret 4

get_count:
// не принимаем параметры, просто считаем количество объектов

// берем текущее смещение с объектом
mov ecx,[TrainMe(hard_1_0).exe+45B0] { [009E7C00] }
// берем начальное смещение
mov edx,[TrainMe(hard_1_0).exe+45AC] { [009E7BC8] }
// вычисляем разницу в байтах
mov eax,ecx
sub eax,edx
// делим на 4
sar eax,02
ret


create_object:
// наши объекты - 4 байта с записанными в них 999

// с помощью оператора new выделяем память в 4 байта
push 4
call TrainMe(hard_1_0).exe+187C
// опять двигаем за ленивую функцию стек обратно
add esp,04
// записываем 999 в новую память (new записывает адрес в eax)
mov [eax],000003E7

// следующая функция творит магию (= я не разбирался)
// но она перезаписывает ссылки на текущий объект и т.д.

// передаем функции новый адрес объекта через регистр edi
// да, она так работает О_о
mov edi,eax
call TrainMe(hard_1_0).exe+1280

ret


[DISABLE]
dealloc(update_label)
unregistersymbol(update_label)

dealloc(update_label_buffer)
unregistersymbol(update_label_buffer)

dealloc(get_count)
unregistersymbol(get_count)

dealloc(create_object)
unregistersymbol(create_object)

 

 

1. Сделать чит-код добавляющий объекты в количестве до 10000.

Spoiler

[ENABLE]
globalalloc(make_10000, 2048)

label(exit)

// Процедура для создания объектов до 10000
make_10000:

// Смотрим на текущее значение объектов
call get_count
// Наша функция пишет результат в eax - сравним его с 10000
cmp eax,#10000
// Если объектов >= 10000 - выходим из цикла / процедуры
jge exit

// Создаем объект
call create_object
// Возвращаемся в начало к нашей проверке
jmp make_10000

// Завершаем наш сюжет, отпускает нас уже
exit:
// Обновим надпись, для красоты
push eax
call update_label

ret

// Создаем новый поток, который выполнит нашу процедуру
createthread(make_10000)
 
[DISABLE]
dealloc(make_10000)
unregistersymbol(make_10000)

 

 

2. Восполнить разрушенный объект при помощи скриптов CE

Spoiler

[ENABLE]
alloc(make_new, 2048)
globalalloc(current_count, 4)

label(returnhere)
label(originalcode)
label(exit)

make_new:
// мы врываемся в самое серце программы, поэтому
// побудем хорошими людьми и сохраним всё что ей дорого
pushfd
pushad

// восстанавлием 1 объект
call create_object

// записываем текущее количество
call get_count
mov [current_count],eax

// возвращаем значения регистров и флагов
popad
popfd

originalcode:
// в ecx хранилось значение количества объектов после вычитания
// мы возмем текущее значение и передадим его
// push ecx
push [current_count]
call dword ptr [TrainMe(hard_1_0).exe+30B8]

exit:
jmp returnhere

// В данно месте начинается вывод текущего числа объектов
// после вычитания, а значит мы можем досоздать объект
// и вывести новое значение количества
"TrainMe(hard_1_0).exe"+113B:
jmp make_new
nop
nop
returnhere:



[DISABLE]
dealloc(make_new)
dealloc(current_count)
unregistersymbol(current_count)

"TrainMe(hard_1_0).exe"+113B:
push ecx
call dword ptr [TrainMe(hard_1_0).exe+30B8]
//Alt: db 51 FF 15 B8 30 37 01

 

 

3. Сделать так чтобы при вычитание объектов или при их создании, их количество держалось на отметке не меньше 1000 объектов

Spoiler

[ENABLE]
// собственно весь смысл в том, что при удалении
// и создании мы должны проверять, а не досоздать ли до 1000

// решил сделать функцию, которую буду вызывать после
// прибавления / вычитания

// собственно функция
globalalloc(make_1000, 2048)
// сюда будем писать адрес, откуда нас вызвали
globalalloc(return_addr, 4)

globalalloc(current_count, 4)

label(return)
label(loop)

current_count:
dd 0

make_1000:
// переносим адрес возврата во вспомогательный регистр
// как-будто мы ничего и не вызывали
pop [return_addr]

// сохраняем состояние регистров
pushfd
pushad

// смотрим, а нужно ли вообще что-то добавлять?
loop:
call get_count
cmp eax,#1000
jge return

// если было нужно - досоздаем объект и так пока не будет 1000
call create_object
jmp loop

// самая маковка
return:
// записываем текущее количество объектов
mov [current_count],eax

// возвращаем значения регистров на место
popad
popfd

// довызываем функцию itow_s
push [current_count]
call dword ptr [TrainMe(hard_1_0).exe+30B8]

// возвращаем адрес откуда нас вызвали в стек
// иначе ret не знает куда прыгать
push [return_addr]
ret

// встраиваемся в itow_s при создании объекта
TrainMe(hard_1_0).exe+11A4:
call make_1000
nop
nop

// встраиваемся в itow_s при вычитании объекта
TrainMe(hard_1_0).exe+113B:
call make_1000
nop
nop


[DISABLE]
dealloc(make_1000)
unregistersymbol(make_1000)

dealloc(current_count)
unregistersymbol(current_count)

TrainMe(hard_1_0).exe+11A4:
push eax
call dword ptr [TrainMe(hard_1_0).exe+30B8] { ->MSVCR90.itow_s }

TrainMe(hard_1_0).exe+113B:
push ecx
call dword ptr [TrainMe(hard_1_0).exe+30B8] { ->MSVCR90.itow_s }

 

 

4. Так же для чуть более легкого тестирования добавил функцию сброса объектов в 0:

Spoiler

[ENABLE]
//code from here to '[DISABLE]' will be used to enable the cheat
globalalloc(make_zero, 2048)

make_zero:
// просто делаем то, что и вычитание, только сразу до нуля
// фактически сдвигая текущий указатель на последний объект до нуля
mov eax,[TrainMe(hard_1_0).exe+45AC]
mov [TrainMe(hard_1_0).exe+45B0],eax

// обновим строку
call get_count
push eax
call update_label

ret

createthread(make_zero)

[DISABLE]
//code from here till the end of the code will be used to disable the cheat
dealloc(make_zero)
unregistersymbol(make_zero)

 

 

  • Плюс 3

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Отличная работа

 

1 час назад, srg91 сказал:

// это хорошая функция, она сама почистила стек за собой

:D

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Можно написать скрипт в теге кода под спойлером и пару слов как было сделано. Таблицы некогда проверять

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
6 hours ago, GameHacker said:

Я не смотрел ващи ну эти скрипты, сам взломал

вот таблица

http://rgho.st/8grPswkRr

 

Не очень похоже, цифра меняется (причем даже близко не на 10000) и сразу после этого вылетает. 

Плюс весь смысл в том, чтобы досоздать нужное количество объектов не сломав TrainMe, мне кажется твоя таблица этого не делает.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Сейчас я попробую... Скрипты не смотрел - у мня тут своя техника :D  

PS: 

Сейчас только лазить перестанут по квартирам со своими выборами..  

Хотя тут уже не докажешь - смотрел я или не смотрел.. Будем ждать новую подобную версию. Без готового решения.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
20 минут назад, LIRW сказал:

Сейчас я попробую...

Го лучше есп врагов и аномалий на сталкера пилить))

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

хм интересно, ответы через 7 8 лет))

а актуально делать ответ когда даже сам автор выложил его?)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

выложите новый траинми

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
3 часа назад, X86Jumps сказал:

а актуально делать ответ когда даже сам автор выложил его?)

 

5 часов назад, LIRW сказал:

Будем ждать новую подобную версию. Без готового решения.

 

Окей. Решение выложили, тему закрываю

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
Гость
Эта тема закрыта для публикации ответов.

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

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

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