JMP на свою функцию

Тема в разделе "WASM.WIN32", создана пользователем Darkcloud, 12 фев 2007.

  1. Darkcloud

    Darkcloud New Member

    Публикаций:
    0
    Регистрация:
    29 авг 2006
    Сообщения:
    8
    Честно говоря не очень в этом разбираюсь, сделал как показалось логичным, но ничего не работает.
    Код (Text):
    1. typedef struct PATCH    {
    2.     BYTE b1;
    3.     DWORD address;     
    4.     PATCH() { b1 = 0x9E;};
    5. }PATCH;
    6.  
    7. void PATCH_PROC()  
    8. {
    9.     char *s_msg;
    10.     __asm mov ebp,eax; // это оригинальный код который
    11.     __asm cmp ebp,-1;  // был на месте моего JMP
    12.     __asm push eax;
    13.     __asm push ecx;
    14.     __asm push edx;
    15.     __asm push ebx;
    16.     __asm mov s_msg,esp
    17.     __asm push esp;
    18.     __asm push esi;
    19.     l.AddToLog(s_msg);
    20.     __asm pop eax;
    21.     __asm pop ecx;
    22.     __asm pop edx;
    23.     __asm pop ebx; 
    24.     __asm pop esp;
    25.     __asm pop esi;     
    26. }
    27.  
    28. //..... DllMain
    29. DWORD dwDummy;
    30. LPVOID mem = (LPVOID)0x0053F4E7;
    31. PATCH p;
    32. p.address = (DWORD)PATCH_PROC;
    33.  
    34. //sizeof(p) = 5, граница выравнивания 1 байт
    35. VirtualProtect(mem, sizeof(p), PAGE_EXECUTE_READWRITE, &dwDummy);
    36. memcpy(mem,&p,sizeof(p));
    37. VirtualProtect(mem, sizeof(p), dwDummy , &dwDummy);
    Патчит какую то ерунду, даже записывает не ту информацию , что в p =(
    Смотрю через OllyDgb.
     
  2. crypto

    crypto Active Member

    Публикаций:
    0
    Регистрация:
    13 дек 2005
    Сообщения:
    2.533
    Darkcloud
    В твоей PATCH_PROC уже куча ошибок.

    mov ebp,eax ;eax имеет неизвестное науке значение, ebp, который будет указателем фрейма, ты портишь
    cmp ebp,-1; непонятно, зачем проверка, ее результатами ты не пользуешься
    mov s_msg,esp4; а в стеке фигня всякая к этому моменту

    порядок выталкивания из стека должен быть обратным по отношению к заталкиванию (FILO - first in last out, т.е. последнее заpushенное значение должно быть первым заpopленным)
     
  3. DelExe

    DelExe New Member

    Публикаций:
    0
    Регистрация:
    22 авг 2005
    Сообщения:
    165
    Darkcloud
    Ассемблерный код это вообще что-то странное.
    Адрес места правки должен вычисляться динамически. Не всегда DLL загрузиться по нужному адресу.
    Что это за конструктор в середине структуры? Если уж заполняешь её - так в одном месте.
    Какая польза с оригинального кода если пролог твоей функции void PATCH_PROC() ещё никто не отменял?

    Да и тему в WASM.BEGINNERS нужно было размещать.

    P.S. Что такое 9E ? sahf ?
     
  4. Darkcloud

    Darkcloud New Member

    Публикаций:
    0
    Регистрация:
    29 авг 2006
    Сообщения:
    8
    Оригинальный код НЕ патченной программы выглядит так
    Я хочу заменить это на jmp 12345678, где 12345678 адрес моей функции
    По крайней мере в OllyDbg можно так заменить и jmp по размеру(если адрес не short) действительно занимает 5 байт !
    Далее после вызова процедуры(а она у меня ещё ни разу не вызывалась, т.к. патчится неверно) должны выполниться оригинальные команды, т.е.
    При этом регистр esi всегда(в данном контексте) указывает на строку.
    Пожтому я адрес копирую в указатель, ну и регистры засовываю в стек, потом делаю некоторые операции(в данном случает просто l.AddToLog(s_msg)), потом вытаскиваю и стека, и далее идее должно продолжиться выполнение программы,
    т.е. долже выполниться код который идёт в оригинале после cmp ebp,-1.
    Что не так, у меня даже memcpy нормально не копирует, копирует ккаую то чушь... =(
    Я думал 9E - это jmp. По крайней мере, если я в OllyDbg заменяю кусок кода на jmp 12345678, код изменяется на 9E 12345678.

    Какая разница где конструктор стоит ? Просто первый байт всегда один и тот же, вот и заполняю к конструкторе.
    Пролог ? Это что такое ?
    Тему можете переместить хоть в WASM.MEGANOOBS, главное скажите что не так...
     
  5. DelExe

    DelExe New Member

    Публикаций:
    0
    Регистрация:
    22 авг 2005
    Сообщения:
    165
    Darkcloud
    E9 - jmp а не 9E
    Твой код анализируют люди. Им не очень интересно разбираться в хитросплетениях кода.
    Пролог это например push ebp/mov ebp, esp
    Сделай NAKED функцию. В её конце вместо RET исполни оригинальные команды и передай управление дальше.
    Оригинальные команды следует вызывать в конце работы твоей функции. (иногда на самом нечале - но это сейчас не для тебя)
     
  6. crypto

    crypto Active Member

    Публикаций:
    0
    Регистрация:
    13 дек 2005
    Сообщения:
    2.533
    Darkcloud
    К чему такие сложности? Распредели код своего патча по свободным от кода дыркам программы и срасти куски кода jmp-ами.
     
  7. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    фигня какая-то. почитай мою статью про сплайсинг. https://forum.antichat.ru/thread32176.html я вроде нормально расписал что к чему и как делать.
    я написал и какой опкод, и как считать разницу, и как патчить и вообще полезно тебе будет.
    а тему реально надо в BEGINNERS.
     
  8. DelExe

    DelExe New Member

    Публикаций:
    0
    Регистрация:
    22 авг 2005
    Сообщения:
    165
    Darkcloud
    Дешовый 5 минутный пример:

    Код (Text):
    1. int origRetAddr = 0x0053F4E7 + 5;
    2.  
    3. /* static  */
    4. void __declspec(naked) PATCH_PROC()
    5. {
    6.     __asm
    7.     {
    8.         push ebp
    9.         mov ebp, esp
    10.         sub esp, 64 //make room for one local variable
    11.         pushad
    12.     }
    13.    __asm mov s_msg, esi
    14.    l.AddToLog(s_msg);
    15.  
    16.     __asm
    17.     {
    18.         popad
    19.         mov esp,ebp
    20.         pop ebp
    21.  
    22.         // original commands
    23.         mov ebp,eax  
    24.         cmp ebp,-1
    25.  
    26.         jmp origRetAddr // return
    27.     }
    28. }
    Если тебе нужно пропатчить воспользуйся советом crypto
    Если динамически изменять/читать инфу - слушать совет Great гуглить и читать про сплайсинг.

    P.S. И на старуху найдёться ...
    У меня была ошибка jmp origRetAddr+5 не катит. Сразу добавь 0x0053F4E7+5. Иначе вычитаешь непонятно что.
     
  9. Darkcloud

    Darkcloud New Member

    Публикаций:
    0
    Регистрация:
    29 авг 2006
    Сообщения:
    8
    Всем спасибо, особенно DelExe. Теперь почти всё работает, правда остался один очень неприятный баг =(
    При вызове функции программа через некоторое время вылетает. Причём не на любой функции вылетает, например HandlerFunc1 проходит отлично, но она ничего и не далает. А вот с HandlerFunc2 - хреново.
    Код (Text):
    1. char *s_msg;
    2. DWORD origRetAddr = 0x0053F4E7 + 5;
    3. FILE *f;
    4.  
    5. void HandlerFunc1()
    6. {
    7.      int k = 10+1;
    8. }
    9.  
    10. void HandlerFunc2()
    11. {
    12.     f = fopen("C:\\log.txt","a");
    13.     fprintf(f,"%s",s_msg); //тут можно написать даже fprintf(f,"Hi, yo") - всё равно эффект тот же
    14.     fclose(f);
    15. }
    16. void __declspec (naked) PATCH_PROC()   
    17. {  
    18.     __asm push esp;
    19.     __asm push eax;
    20.     __asm push ecx;
    21.     __asm push edx;
    22.    
    23.     __asm mov eax,esp;
    24.     __asm mov DWORD PTR[s_msg],eax;
    25.     //HandlerFunc1(); //- вызов функции прохдит нормально
    26.     HandlerFunc2(); //- а при выхове этой функции программы вылетает
    27.  
    28.     __asm pop edx;     
    29.     __asm pop ecx;
    30.     __asm pop eax;
    31.     __asm pop esp;
    32.     __asm mov ebp,eax;
    33.     __asm cmp ebp,-1;
    34.     __asm jmp origRetAddr;
    35.        
    36. }
    Все регистры проверил, после выхода из моей функции(PATCH_PROC), все они имею точно такое же значиние, что и при входе в функцию.
    Правда может я что то упустил ? Проверил EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI
    Может ещё какие есть ?
     
  10. DelExe

    DelExe New Member

    Публикаций:
    0
    Регистрация:
    22 авг 2005
    Сообщения:
    165
    Darkcloud
    __asm mov eax,esp; // Получить указатель вершины стека
    __asm mov DWORD PTR[s_msg],eax; // Записать указатель вершины стека в s_msg

    Вопрос: что ты хочешь увидеть на вершине стека? __asm push edx; ?

    P.S. Всё-равно не понимаю смысловую нагрузку ассемберного кода, что там проверять по eax если регистр затёртый вызовом HandlerFunc2();
     
  11. Darkcloud

    Darkcloud New Member

    Публикаций:
    0
    Регистрация:
    29 авг 2006
    Сообщения:
    8
    Дело в том, что esp ссылается на строку, которую мне надо получить.
    Сначала я писал просто
    __asm mov DWORD PTR[s_msg],esp;
    но программа выдавала на этом месте Access Violation(х3 почему), поэтому я решил сначала скопировать в eax, а потом уж оттуда брать. И это работает - в файл дествительно сохраняется требуемая строка, только потом программа вылетает =(
    Я ничего не проверяю по eax... Я сохраняю указатель на строку в глобальную переменную s_msg, из которой потом читаю и сохраняю в файл.
    З.Ы. тут подумал, может строка кривая и не всегда заканчивается \0 символом... щас проверю...
     
  12. DelExe

    DelExe New Member

    Публикаций:
    0
    Регистрация:
    22 авг 2005
    Сообщения:
    165
    Darkcloud
    При засылке в стек данных регистр ESP уменьшаеться. При выталкивании данных регистр увеличивается.
    Команды push/pop изменяют регистр ESP.
    Команда mov eax,esp занесёт в регистр EAX указатель на вершину стека ESP. На вершине стека лежит edx
    Содержимое стека в момент выполнения команды mov eax,esp:
    [esp +0] edx
    [esp +4] ecx
    [esp +8] eax
    [esp +C] esp (esp в момент входа в функцию PATCH_PROC)
    [esp +10] eip
    +............

    Если у тебя строка выводится, то как я понимаю, ты ожидаешь двойной указатель на строку. Указатель что находиться в регистре EDX ?
     
  13. Darkcloud

    Darkcloud New Member

    Публикаций:
    0
    Регистрация:
    29 авг 2006
    Сообщения:
    8
    Ну про регистр esp я не знал, хотя в моём случае edx и esp отличаются
    Указатель у меня записывается правильно, тут дело даже не в этом.
    НЕ РАБОТАЕТ даже если записать так.
    Код (Text):
    1.     __asm push eax;
    2.     __asm push ecx;
    3.     __asm push edx;
    4.     __asm push ebx;
    5.     __asm push ebp;
    6.     __asm push esi;
    7.     __asm push edi;
    8.  
    9.     Beep(100,100); //вызов простой апи функции,
    10.                          //если её закомментировать, то всё ОК
    11.  
    12.     __asm pop edi;
    13.     __asm pop esi;
    14.     __asm pop ebp;
    15.     __asm pop ebx; 
    16.     __asm pop edx;     
    17.     __asm pop ecx;
    18.     __asm pop eax;
    19.  
    20.     __asm mov ebp,eax;
    21.     __asm cmp ebp,-1;
    22.     __asm jmp origRetAddr; //DWORD origRetAddr
    Тотальный анализ регистров показал следующие изменение между рабочим и не рабочим вариантом.
    SetLastError(ERROR_SUCCESS), пробовал ставить - не помогает.
    Что такое EFL 00000217 (NO,B,NE,BE,NS,PE,GE,G) ?

    З.Ы. это я извращаюсь над mirc клиентом, может там какая то защита есть ?
     
  14. DelExe

    DelExe New Member

    Публикаций:
    0
    Регистрация:
    22 авг 2005
    Сообщения:
    165
    Darkcloud
    Мне что-то подсказывает что тебе немного рано пользоваться технологиями сплайсинга. Для начала стоит изучить ассембер, понять какие регистры стоит сохранять (в зависимости от компилятора), что такое this, порядок помещения аргументов в стек в зависимости от конвенций вызова (__cdecl, __fastcall, __stdcall)...

    Так что считаю - пока код будет доведён до нужного состояния у кого-то из нас не выдержит сердце :)
    Есть книги прекрасного автора Криса Касперски. С них начинали многие. Тебе пригодятся "Фундаментальные основы хакерства", "Образ мышления - дизассемблер IDA". Ну и книги по ассемблеру - их куча в электронном виде.
     
  15. Darkcloud

    Darkcloud New Member

    Публикаций:
    0
    Регистрация:
    29 авг 2006
    Сообщения:
    8
    DelExe, почему рано ? норм =) Что такое this и конвенции вызова я и так знаю, только какой от этого прок здесь ? У Beep, как и у всех апи функций __stdcall и что мне это даёт ? Я создавал свою пустую stdcall функцию и все проходило нормально.
    Да и крутым хакером я не хочу быть =) ,обсуждаемый код мне нужен для вполне мирных целей.
    Скорей всего дествительно нужо разобраться самому - либо здесь действительно какая то защита есть, либо что то ооочень простое, что я упустил =)
    В любом случае - спасибо, тему можно считать закрытой.
     
  16. Darkcloud

    Darkcloud New Member

    Публикаций:
    0
    Регистрация:
    29 авг 2006
    Сообщения:
    8
    Ну вот и всё, проблема решена. Оказывается место jump-а я выбрал неудачо, там после вызова любого апи изменялись вот эти "регистры" (или что это ? =))
    как их push-ить и pop-ить - х3, явно не регистры общего назначения.
    push/pop ES естественно не работает.
    Зато если поставить JMP немного выше(там всё равно есть указатель на нужную мне строку), что всё работает с первого раза =)
    Вот и всё.