Привет.
Решил сразу вторую часть статьи написать.
Прочитайте вначале это:Малварь как искусство - Самомодификация и генерация кода на лету в си. Часть 1. Вкуриваем суть.
Итак в первой части, мы научились генерировать код при помощи опкодов и запускать его в своей программе.
Теперь давайте запустим какую-нить функцию, причём не просто мат. функцию, а например функцию, которая-бы что-то выводила на экран. :)
Зачем это нужно:
1. Если у вас есть какая-то часть кода, которую нужно скрыть (т.е. сплоиты и т.д.).
2. Хотите скрыть часть кода от реверсера или антивируса.
Итак приступим:
Допустим у вас есть код, который нужно скрыть. Для теста мы будем использовать такую функцию:
Ну т.е. просто печатает на экран слово "HI!".
Задача, запустить её из своего кода. Имея бинарный код этой функции.
Итак приступим:
1)Как получить бинарный код нужной функции:
Нужно скопировать секцию кода функции и секцию данных этой функции.
Вот примерно как это сделать:
Программа сохранит в Demo32.bin бинарный код функции. В си-код преобразовать можно так:Информация - Как преобразовать бинарник программы в сишный код
Немного по коду (собирал на вижуалке):
1. #pragma optimize( "", off ) - Нужно отключить оптимизацию компилятора и обязательно собирать в режиме релиз (это важно).
2. Код нашей функции теперь выглядит так:
char buff1[4]; - Это данные, т.к. мы не можем скопировать секцию данных, зато можем генерировать эти данные на стеке. :)
int (*_printf) (const char *,...) - Указатель на printf, т.к. у каждого компьютера это будет разный адрес.
3. Ну тут думаю понятно, вычисляем длину функции, далее копируем в специальный буфер и этот буфер сохраняем в файл:
2)Ну далее нам нужно преобразовать бинарный код в си-код, как это сделать я сказал выше.
У меня получилось так:
Далее пишем программу запуска кода (тоже вижуалка):
Немного по коду:
1) Код, который будем запускать:
2)Указатели на printf и на нашу функцию:
3)В общем-то делаем разрешение на запуск и запускаем:
Получаем:
Таким образом можно запускать сплоиты. Шифрованный код и т.д.
Как видите нет ничего сложного ! :)
Решил сразу вторую часть статьи написать.
Прочитайте вначале это:Малварь как искусство - Самомодификация и генерация кода на лету в си. Часть 1. Вкуриваем суть.
Итак в первой части, мы научились генерировать код при помощи опкодов и запускать его в своей программе.
Теперь давайте запустим какую-нить функцию, причём не просто мат. функцию, а например функцию, которая-бы что-то выводила на экран. :)
Зачем это нужно:
1. Если у вас есть какая-то часть кода, которую нужно скрыть (т.е. сплоиты и т.д.).
2. Хотите скрыть часть кода от реверсера или антивируса.
Итак приступим:
Допустим у вас есть код, который нужно скрыть. Для теста мы будем использовать такую функцию:
Код:
void demo ()
{
printf (" HI! \n");
return 0;
}
Ну т.е. просто печатает на экран слово "HI!".
Задача, запустить её из своего кода. Имея бинарный код этой функции.
Итак приступим:
1)Как получить бинарный код нужной функции:
Нужно скопировать секцию кода функции и секцию данных этой функции.
Вот примерно как это сделать:
Код:
#pragma optimize( "", off )
#include "stdafx.h"
#include "stdio.h"
#include "string.h"
void Demo(int (*_printf) (const char *,...) )
{
char buff1[4];
buff1[0]='H';
buff1[1]='i';
buff1[2]='!';
buff1[3]='\0';
_printf(buff1);
return;
}
void _bild()
{
FILE *f;
void (*_Demo) (int (*) (const char *,...));
void (*_Bild) ();
_Demo=Demo;
_Bild=_bild;
int func_len = (unsigned int) _Bild - (unsigned int) _Demo;
f=fopen("Demo32.bin","wb");
for (int a=0;a<func_len;a++)
fputc(((int) buff[a]),f);
fclose(f);
while (1);
}
int main(int argc, char* argv[])
{
_bild();
return 0;
}
#pragma optimize( "", on )
Программа сохранит в Demo32.bin бинарный код функции. В си-код преобразовать можно так:Информация - Как преобразовать бинарник программы в сишный код
Немного по коду (собирал на вижуалке):
1. #pragma optimize( "", off ) - Нужно отключить оптимизацию компилятора и обязательно собирать в режиме релиз (это важно).
2. Код нашей функции теперь выглядит так:
Код:
void Demo(int (*_printf) (const char *,...) )
{
char buff1[4];
buff1[0]='H';
buff1[1]='i';
buff1[2]='!';
buff1[3]='\0';
_printf(buff1);
return;
}
char buff1[4]; - Это данные, т.к. мы не можем скопировать секцию данных, зато можем генерировать эти данные на стеке. :)
int (*_printf) (const char *,...) - Указатель на printf, т.к. у каждого компьютера это будет разный адрес.
3. Ну тут думаю понятно, вычисляем длину функции, далее копируем в специальный буфер и этот буфер сохраняем в файл:
Код:
int func_len = (unsigned int) _Bild
- (unsigned int) _Demo;
char buff[1000];
memcpy (buff, _Demo, func_len);
f=fopen("Demo32.bin","wb");
for (int a=0;a<func_len;a++)
fputc(((int) buff[a]),f);
fclose(f);
2)Ну далее нам нужно преобразовать бинарный код в си-код, как это сделать я сказал выше.
У меня получилось так:
Код:
static char code2[] =
{
0x55, 0x8b, 0xec, 0x51, 0x8d, 0x45, 0xfc, 0x50, 0xc7, 0x45, 0xfc, 0x48, 0x69, 0x21, 0x00, 0xff,
0x55, 0x08, 0x83, 0xc4, 0x04, 0x8b, 0xe5, 0x5d, 0xc3, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc
};
Далее пишем программу запуска кода (тоже вижуалка):
Код:
#define _CRT_SECURE_NO_WARNINGS
#include "stdafx.h"
#include "stdio.h"
#include "string.h"
#include "windows.h"
int main(int argc, char* argv[])
{
static char buff[1000];
int(*_printf) (const char *, ...);
void(*_Demo) (int(*) (const char *, ...));
static char code2[] =
{
0x55, 0x8b, 0xec, 0x51, 0x8d, 0x45, 0xfc, 0x50, 0xc7, 0x45, 0xfc, 0x48, 0x69, 0x21, 0x00, 0xff,
0x55, 0x08, 0x83, 0xc4, 0x04, 0x8b, 0xe5, 0x5d, 0xc3, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc
};
int code_size = sizeof(code2);
memcpy(buff, code2, sizeof(code2));
_printf = printf;
_Demo = (void(*) (int(*) (const char *, ...)))&buff[0];
DWORD oldprotect;
VirtualProtect(_Demo, sizeof(code2), PAGE_EXECUTE, &oldprotect);
_Demo(_printf);
while (1);
return 0;
}
Немного по коду:
1) Код, который будем запускать:
Код:
static char code2[] =
{
0x55, 0x8b, 0xec, 0x51, 0x8d, 0x45, 0xfc, 0x50, 0xc7, 0x45, 0xfc, 0x48, 0x69, 0x21, 0x00, 0xff,
0x55, 0x08, 0x83, 0xc4, 0x04, 0x8b, 0xe5, 0x5d, 0xc3, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc
};
2)Указатели на printf и на нашу функцию:
Код:
int(*_printf) (const char *, ...);
void(*_Demo) (int(*) (const char *, ...));
_printf = printf;
_Demo = (void(*) (int(*) (const char *, ...)))&buff[0];
3)В общем-то делаем разрешение на запуск и запускаем:
Код:
DWORD oldprotect;
VirtualProtect(_Demo, sizeof(code2), PAGE_EXECUTE, &oldprotect);
_Demo(_printf);
Получаем:
Таким образом можно запускать сплоиты. Шифрованный код и т.д.
Как видите нет ничего сложного ! :)
Последнее редактирование: