Модераторы: bsa
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как реализовать распаковку кода (машинного)? 
:(
    Опции темы
wvlg
Дата 3.6.2008, 09:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 17
Регистрация: 2.6.2008

Репутация: нет
Всего: нет



 Проблема в следующем. Пользователь вводит машинный код (то, что видно в дизассемблере в виде байт, а он их дизасемблирует отображает команды). Неважно как (из файла или просто вводом строки или по сети (у меня по сети этот код приходит). Но я просто никак не погу придумать как это реализовать, скажем в Borland Builder C++ (6.0)? На ассемблере нет проблем. Делаем область памяти с доступом RWE пишем туда код и нет проблем. Но на ЯВУ как(Конкрестно на С)?  Сделать там ассемблеревскую вставку? Для меня проблематично. Хотя бы в плане адресации памяти. Не знаю как с этим быть. Да еще и доступ нужно открыть соответствующий.

(К стати, как альтернатива, интересует и возможность написания интерпритатора машинного кода, если можно так сказатьsmile Т.е. "маленького" дизассемблера. Мне не очень много инструкций нужно. Всего, порядка 20ти. Но где брать МНАЫ на эту тему вообще не знаю. Не отказался бы и от такой информации или ссылок на неё)
З.Ы. Я тут новичек, так что прошу прощения, если что не так.

Это сообщение отредактировал(а) wvlg - 3.6.2008, 09:19
PM MAIL   Вверх
ksili
Дата 3.6.2008, 09:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2069
Регистрация: 3.11.2005
Где: Красноярск

Репутация: нет
Всего: 17



Цитата(wvlg @  3.6.2008,  13:12 Найти цитируемый пост)
Сделать там ассемблеревскую вставку

так:
Код

___asm{   .......  }

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

Интерпретатор машинного языка и дизассемблер - это кажется разные вещи, почти обратные.


Цитата(wvlg @  3.6.2008,  13:12 Найти цитируемый пост)
Но где брать МНАЫ

что это? 


--------------------
Ничто так не развивает аналитическое мышление, как отладка сложной программы без возможности пошагового выполнения (с)
PM MAIL   Вверх
wvlg
Дата 3.6.2008, 09:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 17
Регистрация: 2.6.2008

Репутация: нет
Всего: нет



Цитата(ksili @  3.6.2008,  09:39 Найти цитируемый пост)
Но где брать МНАЫчто это? 

Это опечатка. МАНЫ- мануалы... Доступные, готовые руководства к написанию дизассемблера. Пример с пояснением, в моем понимании.


Цитата(ksili @  3.6.2008,  09:39 Найти цитируемый пост)
Интерпретатор машинного языка и дизассемблер - это кажется разные вещи, почти обратные.


 Поэтому я и сказал:"интерпритатора машинного кода, если можно так сказать"


А насчет ассемблеровской вставки как Вы себе представляет, что я там должен написать!!?? По-любому существующему адресу вставить то, что я хочу  и выполнить? Для начала память надо выделить. Дать ей доступ R\W\E. Потом записать туда то, что нужно и выполнить.

Это сообщение отредактировал(а) wvlg - 3.6.2008, 09:52
PM MAIL   Вверх
ksili
Дата 3.6.2008, 09:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2069
Регистрация: 3.11.2005
Где: Красноярск

Репутация: нет
Всего: 17



Цитата(wvlg @  3.6.2008,  13:50 Найти цитируемый пост)
А насчет ассемблеровской вставки как Вы себе представляет, что я там должен написать!!??

Так вы объясните нормально, что вам нужно.
Цитата(wvlg @  3.6.2008,  13:50 Найти цитируемый пост)
Доступные, готовые руководства к написанию дизассемблера

на www.wasm.ru


--------------------
Ничто так не развивает аналитическое мышление, как отладка сложной программы без возможности пошагового выполнения (с)
PM MAIL   Вверх
wvlg
Дата 3.6.2008, 10:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 17
Регистрация: 2.6.2008

Репутация: нет
Всего: нет



Да, пожалуй, самое главное я не сказал. Извиняюсь. Задумался слишком, наверное.

Итак. Пользователь вводит машинный код. В этом коде используются 4 регистра процессора. (два задают адреса строки символов(на оба одинаковый адрес), третий счетчик, в 4й происходит запись символа и операции над ним). Необходимо подать на эти регистры нужные нам значения. У нас в программе есть строка, адрес, по которому она лежит и нужно "положить" в регистры. А затем необходимо запустить этот самый пользовательский код на исполнение и вернуться в основную часть программы. Вот.


Это сообщение отредактировал(а) wvlg - 3.6.2008, 10:40
PM MAIL   Вверх
ksili
Дата 3.6.2008, 10:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2069
Регистрация: 3.11.2005
Где: Красноярск

Репутация: нет
Всего: 17



Допустим юзер вводит команду в Edit1, регистры соответственно в Edit2, Edit3 и Edit4.
Тогда можно сделать примерно так (в Borland Builder C++ 6.0):
Код

int ra, rb, rc;
ra = StrToInt(Edit2->Text);
rb = StrToInt(Edit3->Text);
rc = StrToInt(Edit4->Text);

__asm
    {
     mov eax, ra
     mov ebx, rb
     mov ecx, rc
    }
if(Edit1->Text=="int 21h")   
    asm { int 21h }
else if(Edit1->Text=="int 10h")   
    asm { int 10h }
.....


Но могут быть проблемы из-за использования регистров. Поэтому лучше в начале вставки делайте PUSHA, а в конце POPA

Это сообщение отредактировал(а) ksili - 3.6.2008, 10:43


--------------------
Ничто так не развивает аналитическое мышление, как отладка сложной программы без возможности пошагового выполнения (с)
PM MAIL   Вверх
W4FhLF
Дата 3.6.2008, 10:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


found myself
****


Профиль
Группа: Участник Клуба
Сообщений: 2831
Регистрация: 2.12.2006

Репутация: 2
Всего: 121



Я так и не понял, что конкретно надо. Интерпретатор, дизассемблер, свой ассемблер или что вообще? Давайте определимся, ненужно сумбурности и длинных описаний, приведите какой-нибудь обощённые пример и опишите последовательно, что должно происходить. 


--------------------
"Бог умер" © Ницше
"Ницше умер" © Бог
PM ICQ   Вверх
wvlg
Дата 3.6.2008, 11:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 17
Регистрация: 2.6.2008

Репутация: нет
Всего: нет



Входные данные:
Пользовательская строка с машинным кодом. И ВСЕ. 


К ней требования: максимальный размер 500 байт
В коде для адресации могут использоваться только 2 регистра: EBX, EAX.
Для работы с данными Регистр AL - 1 байт

Необходимо подать на регистры EAX,EBX адрес переменной с которой код пользователя будет работать. (по поводу размера отдельная тема, решаема...)

Далее необходимо ЗАПУСТИТЬ строку которую ввел пользователь на исполнение.


Т.е. пример:
У нас есть адрес 0x018855aah. Записываем его в регистр EBX и его же в EAX. (Т.к. заранее мы не знаем какой из них будет выбран пользователем, но точно знаем, что один из них)
Пользователь ввел:
8a03

Это - mov AL, Byte PTR DS:[EBX]-это в дизассемблере мы это увидим. А пользователь ввел всего лишь
8a03
Мы должны отправить 8a03 в память на исполнение, перед этим заполнив регистры адресами.

Это сообщение отредактировал(а) wvlg - 3.6.2008, 11:19
PM MAIL   Вверх
jonie
Дата 3.6.2008, 11:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 5613
Регистрация: 21.8.2005
Где: Владимир

Репутация: 6
Всего: 118



если ты знаешь как это реализовать на ASM, то зачем тебе билдер? ты можешь это реализовать на асме, и обернуть все это в библиотку, которую можно использовать уже в билдере.


--------------------
Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет...
PM MAIL Jabber   Вверх
wvlg
Дата 3.6.2008, 11:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 17
Регистрация: 2.6.2008

Репутация: нет
Всего: нет



Цитата(jonie @  3.6.2008,  11:20 Найти цитируемый пост)
ы можешь это реализовать на асме, и обернуть все это в библиотку

М... Думал я над этим. Просто на асме придется "попотеть". Библиотека ведь будет под WIn. Могу ошибок понаделать миллион, хотя...
 Там все те же вопросы по поводу выделения секций памяти и т.п. На асме я себе это еще хотя бы представляю (но не знаю на сколько это будет сложно). А вот в билдере... Да и просто интересно... Ведь если задачу усложнить и видоизменить, то что каждый раз писать на ассемблере?

Добавлено @ 11:36
Цитата(ksili @  3.6.2008,  10:41 Найти цитируемый пост)
if(Edit1->Text=="int 21h")       asm { int 21h }else if(Edit1->Text=="int 10h")       asm { int 10h }

 это команды ассемблера... А пользователь вводит команды процессора...

Это сообщение отредактировал(а) wvlg - 3.6.2008, 11:37
PM MAIL   Вверх
ksili
Дата 3.6.2008, 12:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2069
Регистрация: 3.11.2005
Где: Красноярск

Репутация: нет
Всего: 17



Цитата(wvlg @  3.6.2008,  15:30 Найти цитируемый пост)
это команды ассемблера... А пользователь вводит команды процессора...

Ну так поправить можно:
Код

if(Edit1->Text=="8BC2")   
    asm { mov ax, dx }
else if(Edit1->Text=="50")   
    asm { push ax }
 ..............



--------------------
Ничто так не развивает аналитическое мышление, как отладка сложной программы без возможности пошагового выполнения (с)
PM MAIL   Вверх
W4FhLF
Дата 3.6.2008, 12:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


found myself
****


Профиль
Группа: Участник Клуба
Сообщений: 2831
Регистрация: 2.12.2006

Репутация: 2
Всего: 121



Теперь всё ясно.


Цитата(wvlg @  3.6.2008,  11:13 Найти цитируемый пост)
У нас есть адрес 0x018855aah. Записываем его в регистр EBX и его же в EAX. (Т.к. заранее мы не знаем какой из них будет выбран пользователем, но точно знаем, что один из них)


Код команды mov eax,X0...X3:

Код

B8X3...X0



mov ebx,X0...X3:

Код

BBX3...X0


Xn - n-ый байт в числе.

т.е. X0...X4 - обычный DWORD. например 018855AAh.

Создаёшь два массива в С++:

Код

char mov_eax = {"\xb8\x00\x00\x00\x00"};
char mov_ebx = {"\xbb\x00\x00\x00\x00"};


Пользователь ввёл какой-то адрес, ты переводишь строку в DWORD(unsigned int32) и пишешь по адресам mov_eax[1], mov_ebx[1].

Т.о. ты формируешь две машинные инструкции:
Код

mov eax,an_address
mov ebx,an_address


Цитата(wvlg @  3.6.2008,  11:13 Найти цитируемый пост)
Входные данные:Пользовательская строка с машинным кодом. И ВСЕ. 
К ней требования: максимальный размер 500 байт


Выделяешь массив под шеллкод:

Код

char shellcode[506] = {0};


Далее пользователь вводит любой машинный код, например, как ты сказал: 
Код

8A03


Разделяешь всю введённую строку на байты, т.е. обрабатываешь по два символа, каждые два символа - один байт, т.е. в результате ты должен будешь получить массив: 

Код

0x8A, 0x03


Получил ты этот массив. 

В самое начало shellcode надо поместить команду pushfd, только если тебе надо сохранить среду исполнения перед выполнением пользовательского кода, команда сохранит все регистры и флаги в стеке, после исполнения твоего кода мы восстановим их. Код инструкции:

Код

9C            PUSHFD


Далее, за pushfd в массив shellcode надо поместить две команды mov eax, an_address и mov ebx,an_address. Это осуществляется простым копированием из массивов mov_eax и mov_ebx в начало массива shellcode. 

Теперь копируй в shellcode[10] массив, который получил чуть раньше из введённых пользователем данных.

За ними вставляй(в случае, если был pushfd):

Код

9D            POPFD



Далее, после выполнения пользовательского кода и восстановления среды необходимо вернуться на то место в программе, откуда был вызван шеллкод, для этого надо узнать адрес возврата. Делается это примерно так:

Код

unsigned int here_addr = 0;
__asm {
nop
nop
call lbl
lbl:
pop here_addr // в here_addr адресс инструкии pop here_addr, если к here_addr прибавить размер команды инструкции pop получим нужный нам адрес возврата
}


Соответственно в конец массива shellcode пишешь 
Код

jmp here_code+sizeof(pop here_addr)


Только предварительно поищи в интернете или почитай в манах от Intel'a как формируется код адреса для относительных переходов. 

Всё, теперь можешь исполнять shellcode в памяти. Возможно понадобится выставить аттрибут EXECUTE для массива shellcode, это можно сделать с помощью api VirtualProtect в Windows. Ещё, массив shellcode лучше не делать локальным, ибо может быть включен DEP и тогда на стеке ничего не исполнится.

Добавлено через 5 минут и 16 секунд
Что касается адресации в памяти. Вводимы пользователь код должен быть базонезависимым, иначе тебе придётся прикручивать полноценный дизассемблер и делать анализатор кода, который будет заниматься rebasing'ом. 

Это сообщение отредактировал(а) W4FhLF - 3.6.2008, 12:12


--------------------
"Бог умер" © Ницше
"Ницше умер" © Бог
PM ICQ   Вверх
wvlg
Дата 3.6.2008, 12:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 17
Регистрация: 2.6.2008

Репутация: нет
Всего: нет



ОБАЛДЕТЬ!!!
Как раз то, что я искал. Огромное спасибо! Надо попрбовать. Единственное, как я понял, чтобы вызвать shellcode должно быть что-то типа 

Код

ShellCode_addr=shellcode

И далее где-нибудь

а затем asm вставка, где будет что-то типа
Call ShellCode_addr ?

И, главное, чтобы не возникло проблем с VirtualProtect... Вернее с тем что у памяти доступ будет еще и execute

Добавлено через 9 минут и 47 секунд
Честно говоря, когда сам над этим думал придумалась только одна мысль. Создать указатель на функцию.  Выделить память. Скопировать туда то, что нам нужно. Указателю присвоить значение адреса этой памяти. Вызвать функцию.... Мне казалось, что такое не пройдет. ?

Это сообщение отредактировал(а) wvlg - 3.6.2008, 12:51
PM MAIL   Вверх
W4FhLF
Дата 3.6.2008, 13:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


found myself
****


Профиль
Группа: Участник Клуба
Сообщений: 2831
Регистрация: 2.12.2006

Репутация: 2
Всего: 121



Цитата(wvlg @  3.6.2008,  12:47 Найти цитируемый пост)
а затем asm вставка, где будет что-то типаCall ShellCode_addr ?


если со вставкой, то так:

Код

__asm {
 push eax
 lea eax,shellcode
 call eax
 pop eax
}


Просто на С++ будет так:

Код

void (*pFunc)();
....
pFunc = &shellcode;
pFunc();




Цитата(wvlg @  3.6.2008,  12:47 Найти цитируемый пост)
И, главное, чтобы не возникло проблем с VirtualProtect...


Какие проблемы? Простой вызов:

Код

VirtualProtect((PVOID)&shellcode, sizeof(shellcode), PAGE_EXECUTE_READWRITE, &OldProtect);


Можешь даже делать этот вызов всегда, чтобы оградить себя от лишних проблем. Есть особенность, права доступа назначаются целым страницам памяти, они не могут быть назначены какой-то части страницы. Стандартный размер страницы в windows == 0x1000. Т.е. можешь массив shellcode делать размером 0x1000 и не париться. 



--------------------
"Бог умер" © Ницше
"Ницше умер" © Бог
PM ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0680 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.