1

Тема: Код, який модификується самостійно

Доброго часу доби!
Код, який розташований нижче нормально компілюється Watcom та запускається. Але якщо цей код скомпілювати за допомогою Microsoft Visual Studio 2010, то скомпільована програма запуститься без помилок тільки під середовищем Microsoft Visual Studio 2010 у режимі Release. IDA повертає помилку доступа. Де виникає помилка у коментарях. Допоможіть розібратися!

#include<stdio.h>
#include<stdlib.h>
#include<memory.h>
#include<windows.h>
#define SELF_SIZE ((int)x_self_mod_code-(int)x_self_mod_end)//якщо замінити на реальне значення (20 байт у даному випадку, а не те що покаже Visual Studio 2010) не спрацює також.

__declspec(naked)int x_self_mod_code(int a,int b)
{
    __asm
    {
        mov eax,[esp+4]//Получаем первый аргумент
        call get_eip//Определяем текущее положение в памяти (заталкивается в стек адрес метки get_eip)
get_eip:
        add eax,[esp+8+4]//Складываем/вычитаем из первого аргумента второй (+4 байт - это размер места, занимаемого адресом метки get_eip)
        pop edx//В edx адрес начала инструкции add eax, ...
        xor byte ptr[edx],28h//Меняем add на sub и наоборот
        ret
    }
}
void x_self_mod_end(){};

int main()
{
    int a;
    int (__cdecl*self_mod_code)(int a,int b);
    self_mod_code=(int (__cdecl*)(int,int))VirtualAlloc(NULL, SELF_SIZE, MEM_COMMIT,PAGE_EXECUTE_READWRITE);
    memcpy(self_mod_code,x_self_mod_code,SELF_SIZE);//помилка виникає тут
    for(a=1;a<10;a++)printf("%02X",self_mod_code(4,2));
    printf("\n");
    VirtualFree(self_mod_code, 0, MEM_RELEASE);
    return 0;

0xDADA11C7: Не забувайте про теґ code

Подякували: Дмитро-Чебурашка1

2

Re: Код, який модификується самостійно

Тут, здається потрібно відкрити доступ на Read, write, execute до сегменту .text. Як це зробити?

3

Re: Код, який модификується самостійно

Користуйтеся VirtualProtect функцією, але можете лінкеру сказати, щоб він забезпечив можливість редагування секції.

#pragma comment( linker ,"/SECTION:.text,RWE" )

А взагалі щоби бавитися модифікацією кода  - створюйте хіп з можливістю виконання кода і бавтеся на здоров'ячко - HeapCreate з HEAP_CREATE_ENABLE_EXECUTE

4 Востаннє редагувалося StillPhelix (17.07.2015 12:26:11)

Re: Код, який модификується самостійно

Виправив так:
i

nt main()
{
    HANDLE hHeap;
    hHeap=HeapCreate(HEAP_CREATE_ENABLE_EXECUTE,SELF_SIZE,0);
    int (__cdecl*self_mod_code)(int a,int b);
    self_mod_code=(int (__cdecl*)(int,int))HeapAlloc(hHeap,HEAP_NO_SERIALIZE,SELF_SIZE);
    memcpy(self_mod_code,x_self_mod_code,SELF_SIZE);
    for(int a=1;a<10;a++)printf("%02X",self_mod_code(4,2));
    printf("\n");
    HeapFree(hHeap,HEAP_NO_SERIALIZE,self_mod_code);
    return 0;
}

Але відлагоджувач visual studio 2010 повертає помилку: "Unhandled exception at 0x5b0fc9c7 (msvcr100d.dll) in SelfMod1.exe: 0xC0000005: Access violation writing location 0x00000000".
IDA показує, що аргумент self_mod_code (адреса призначення) функції memcpy =0 (покажчик вказує аж за .text). А хто ж туди пустить на запис у здоровому глузді? Як цю помилку виправити?

5

Re: Код, який модификується самостійно

гадаю, що функцію HeapCreate потрібно також викликати з прапорцем HEAP_NO_SERIALIZE

6

Re: Код, який модификується самостійно

гадаю, що функцію HeapCreate потрібно також викликати з прапорцем HEAP_NO_SERIALIZE

Програма у такому випадку поверне STATUS_ACCESS_VIOLATION (згідно з SDK).

Re: Код, який модификується самостійно

Я вчора дви години медітував на код...   Дякую дуже сильно!!

8 Востаннє редагувалося StillPhelix (18.07.2015 15:54:19)

Re: Код, який модификується самостійно

Дорогу здолає той, хто йде. Тримайте правильний вихідний код (visual studio 2010):

#include<stdio.h>
#include<stdlib.h>
#include<memory.h>
#include<windows.h>
#define SELF_SIZE 0x18//((int)x_self_mod_end-(int)x_self_mod_code)


__declspec(naked)int x_self_mod_code(int a,int b)
{
    __asm
    {
        mov eax,[esp+4]//Получаем первый аргумент
        call get_eip//Определяем текущее положение в памяти (заталкивается в стек адрес метки get_eip)
get_eip:
        add eax,[esp+8+4]//Складываем/вычитаем из первого аргумента второй (+4 байт - это размер места, занимаемого адресом метки get_eip)
        pop edx//В edx адрес начала инструкции add eax, ...
        xor byte ptr[edx],28h//Меняем add на sub и наоборот
        ret
    }
}
void x_self_mod_end(){};

int main()
{
    int a;
    int (__cdecl*self_mod_code)(int a,int b);
    self_mod_code=(int (__cdecl*)(int,int))VirtualAlloc(NULL, SELF_SIZE, MEM_COMMIT,PAGE_EXECUTE_READWRITE);
    printf("error=0x%X, size=0x%X\n",GetLastError(),SELF_SIZE);
    memcpy(self_mod_code,x_self_mod_code,SELF_SIZE);
    for(a=1;a<10;a++)printf("%02X",x_self_mod_code(4,2));
    printf("\n");
    VirtualFree(self_mod_code, 0, MEM_RELEASE);
    return 0;
}