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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Выделение памяти с правами на запуск функции, Выделить память и запустить в ней ф-ю 
V
    Опции темы
MAKCim
Дата 1.4.2008, 22:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

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



Цитата(jeka23 @  1.4.2008,  21:46 Найти цитируемый пост)
но никак не могу найти как это сделать с g++ компилятором..... Может кто-нить подсказать как это делается?

компилятор здесь не причем
нужно использовать mmap() с ненулевым первым параметром
если mmap() возвращает ошибку, значит данный участок линейного адресного пространства использовать нельзя
такой вопрос, создавать новый процесс можно? или все надо делать в контексте текущего?



--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
jeka23
Дата 1.4.2008, 22:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Цитата

нужно использовать mmap() с ненулевым первым параметром
если mmap() возвращает ошибку, значит данный участок линейного адресного пространства использовать нельзя


Я так и делаю: первый параметр mmap - желаемый адрес проецирования бинарника, который я извликаю из самого бинарника. Он железно жашит в бинарнике как 0x33310000, но память в отладчике сразу помечается как out of bounds
В таком же "движке" под винду просто используется желаемый адрес проецирования самого "движка" под адресом 0x33300000, и соответственно бинарник может проецироваться в память рядом с "движком" по адресу 0x33310000. В моем "движке" под линукс нужно просто задать базовый адрес проецирования в виде 0x33300000 и по логике все должно заработать, но только как его задать.... Компилятор тут конечно не причем, таие вещи задаются линковщику, но как... не могу в инете ничег накопать smile 

Цитата

такой вопрос, создавать новый процесс можно? или все надо делать в контексте текущего?


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



PM MAIL   Вверх
RasenHerz
Дата 1.4.2008, 22:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



так вы пишите загрузчик для *.exe файлов? посмотрите сорцы Wine. думаю обычным копированием шелла вы не обойдетесь - между принципиальная разница - разница между сегментацией в Linux и Windows просто огромна. все будет гораздо сложнее если в шелле будет вызываться какой-либо метод, придется очень многое исправлять.... но если вы дадите мне таблицу соответствия ассемблерных команд их hex значению (извините за безграмотность) - к примеру, ret - 0xc3 и т.д., то я возможно чем то смогу вам помочь. и пожалуйста, выложите проблемный кусок кода здесь... я все-таки не телепат... smile 
PM MAIL   Вверх
jeka23
Дата 1.4.2008, 23:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Я очень благодарен Вам за желание помочь.

Загрузчик я не пишу, он уже написан другим человеком, с которым компания потеряла связь. Все что мне нужно сделать - это воспользоваться им из "движка" чтобы подгрузить бинарники и вызвать функции этих бинарников так же в "движке" (понимаю, что уже тошнит от слова "движок", но стараюсь изясняться яснее smile ).

И так:

функция для выделения памяти под бинарник ПОКА выглядет так:

Цитата

virtual void* alloc_pagealign(void* Address, SIZE_T cb)
    {
  int fd2 = open("/tmp/mmaptest2",
    (O_CREAT | O_TRUNC | O_RDWR),
    (S_IRWXU | S_IRWXG | S_IRWXO) );
  Address = mmap(Address, cb, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, fd2, 0);
  return Address;
    }


в самом загрузчике память под бинарник выделяется так:

Цитата

LPBYTE hmod = (LPBYTE)alloc_pagealign((LPVOID)(DWORD_PTR)
  inth.OptionalHeader.ImageBase, ImageSize);


я продефайнил все майкросовские типы, например DWORD, руководитель проекта так попросил.

Функции загрузчика по распатрашению PE заголовков думаю выкладывать нет смысла, они роли не сыграют, к тому же в дебагире 20 раз проверенно - работает четко. OptionalHeader.ImageBase как Вы понимаете - базовый адрес проецирования бинарника, который был вытащен загрузчиком из PE заголовка самого бинарника, и постоянно раввен 0x33310000.

Но вот и тут-то пока все падает с SIGBUS так как только в выделеную память с помошью mmap происходит запись с помошью memcpy - все валицо smile 

Цитата

но если вы дадите мне таблицу соответствия ассемблерных команд их hex значению (извините за безграмотность) - к примеру, ret - 0xc3 и т.д., то я возможно чем то смогу вам помочь


с удовольствием дам, только не могу понять о чем Вы smile , обясните что делать - выложу.



Вообще проблем вроде не должно быть в данной задаче, так как бинарники написаны кросплатформенно и любая ф-ия типа strcpy переписана в самом бинарнике чтобы не ссылаться ни на одну библиотеку винды.

В дальнейшем мне нужно с помошью функции загрузчика GetProcAddr вытащить какую-нибудь функцию из загруженого бинаоника и вызвать ее, как например тут:

Цитата

void (CDECL* SetNameInfo)(naming_info*) = 
    (void (CDECL* )(naming_info*))GetProcAddr(hmod, 114);

  if(!SetNameInfo)
  {
    //error
  } 

  SetNameInfo(&m_bases.ni);


и когда я использовал malloc, то бинарник грузился нормально и на строке кода SetNameInfo(&m_bases.ni); я сравнивал ассемблерский код, нахдящийся по адресу SetNameInfo в отладчике под линуксом и под виндой в аналогичном "движке" - код абсалютно одинаков, кроме смещений, которые заменяет сам загрузчик. Загрузчик работает правильно. Просто при использовании malloc все падало с Sigmentation fault так как malloc не дает права на запуск в памяти, да и использовать malloc нельзя так как загрузчик четко указывает желаемые адреса проецирования, а в malloc такой возможности нет.

Если чего не понятно - с прашивайте, с удовольствием обясню, и еще раз спасибо.
PM MAIL   Вверх
MAKCim
Дата 2.4.2008, 09:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

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



Цитата(jeka23 @  1.4.2008,  22:49 Найти цитируемый пост)
создавать процесс можно, но это получится крайне не красивое решение так как в бинарнике хранятся множество функций, которые нужно вызывать в разных участках "движка", и каждый раз для этого создавать процесс ну никак не будет красиво выглядеть..

зачем?
фишка в том, что можно создать фиктивный исполняемый файл, который будет отображаться через sys_execve как раз чуть ниже 0x33310000 (адрес указывается)
код, отображенный ниже 0x33310000, будет отображать любой образ по адресам >= 0x33310000


--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
xvr
Дата 2.4.2008, 12:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

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



Цитата(jeka23 @ 1.4.2008,  23:55)
И так:

функция для выделения памяти под бинарник ПОКА выглядет так:

Цитата

virtual void* alloc_pagealign(void* Address, SIZE_T cb)
    {
  int fd2 = open("/tmp/mmaptest2",
    (O_CREAT | O_TRUNC | O_RDWR),
    (S_IRWXU | S_IRWXG | S_IRWXO) );
  Address = mmap(Address, cb, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, fd2, 0);
  return Address;
    }


в самом загрузчике память под бинарник выделяется так:

Цитата

LPBYTE hmod = (LPBYTE)alloc_pagealign((LPVOID)(DWORD_PTR)
  inth.OptionalHeader.ImageBase, ImageSize);


я продефайнил все майкросовские типы, например DWORD, руководитель проекта так попросил.

Функции загрузчика по распатрашению PE заголовков думаю выкладывать нет смысла, они роли не сыграют, к тому же в дебагире 20 раз проверенно - работает четко. OptionalHeader.ImageBase как Вы понимаете - базовый адрес проецирования бинарника, который был вытащен загрузчиком из PE заголовка самого бинарника, и постоянно раввен 0x33310000.

Но вот и тут-то пока все падает с SIGBUS так как только в выделеную память с помошью mmap происходит запись с помошью memcpy - все валицо smile 

А зачем выделять память через mmap? Мэпируйте сразу ваш файл (PE) на нужные адреса.
PM MAIL   Вверх
jeka23
Дата 2.4.2008, 12:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Нашел наконец как задать желаемый адрес проецирования, только не могу понять почему ругается:

Код

g++ -g -O -c test.cpp
ld -image-base 0x33300000 test.o
g++ -g -o myapp test.o

ld: bad -rpath option


Кто-нибудь знает как успокоить линковщик? Немогу вообще понять зачем ему rpath если LD_RUN_PATH переменная используется....

Добавлено через 5 минут и 52 секунды
Цитата

А зачем выделять память через mmap? Мэпируйте сразу ваш файл (PE) на нужные адреса. 


Так оно по любому так и получается: alloc_pagealign выделяет память под PE, а потом туда через memcpy заливается сам бинарник. Просто "на нужные адреса" не получается получить память из за того, что мой "движок" не спроецирован на нужные мне адреса, вот и спрашиваю у народа:

Цитата

Нашел наконец как задать желаемый адрес проецирования, только не могу понять почему ругается:

Выделить всёкод C++

g++ -g -O -c test.cpp
ld -image-base 0x33300000 test.o
g++ -g -o myapp test.o
ld: bad -rpath option


Кто-нибудь знает как успокоить линковщик? Немогу вообще понять зачем ему rpath если LD_RUN_PATH переменная используется.... 

PM MAIL   Вверх
jeka23
Дата 2.4.2008, 14:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



....не могу понять, почему вот такой код валится с сигналом SIGBUS:

Код

#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <string.h>

int main()
{
    int fd2 = open("/tmp/q",O_RDWR,0);

    printf("fd: %d\n",fd2);
    void* Address = mmap(0, 100, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, fd2, 0);
    
    printf("addr: %d\n",Address);

    char *s=new char[100];
    memcpy(Address,s,30);

    return 0;
}


Почему я не могу писать в Address?
PM MAIL   Вверх
MAKCim
Дата 2.4.2008, 16:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

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



jeka23,
Цитата(jeka23 @  2.4.2008,  14:38 Найти цитируемый пост)
Почему я не могу писать в Address? 

mmap() точно не возвращает значение MAP_FAILED?
errno равна нулю после mmap()?

ход решения такой
1. формируем специальный исполняемый файл, который будет отображать PE по нужному адресу (0x33310000) через mmap()
сам исполняемый файл будет создан таким образом, что ядро будет отображать его по адресу X < 0x33310000 так, что значение 0x33310000 - X будет равно его размеру
2. пишем загрузчик
загрузчик порождает новый процесс, в контексте нового процесса выполняем
execve(), перадавая в качестве параметра путь к отображаемому PE

если хочешь, могу вечером сделать такой файл, это несложно


--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
jeka23
Дата 2.4.2008, 17:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



MAKCim, очень благодарен, mmap сработал, просто q был нулевого размера, поэтому и валилось. Пока продвигаюсь дальше, вскоре отпишусь и разясню ситуацию, думаю можно будет обойтись без другого процесса..
PM MAIL   Вверх
jeka23
Дата 2.4.2008, 18:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Уважаемые программеры, в последний раз благодарю вас всех за уделенное мне время smile 
Загрузчик заработал, нужно было просто правильно воспользоваться mmap и не важно какие адреса используются, смешно и стыдно smile 

Помечаю пост как "решенный", удачи Вам и еще раз спасибо.



P.S.: Будущее за linux-ом и Россией, так как и то и другое было основано на идее.
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С/С++: Программирование под Unix/Linux"
xvr
  • Проставьте несколько ключевых слов темы, чтобы её можно было легче найти.
  • Не забывайте пользоваться кнопкой "Код".
  • Вопросы мобильной разработки тут
  • Телепатов на форуме нет! Задавайте чёткий, конкретный и полный вопрос. Указывайте полностью ошибки компилятора и компоновщика.
  • Новое сообщение должно иметь прямое отношение к разделу форума. Флуд, флейм, оффтопик запрещены.
  • Категорически запрещается обсуждение вареза, "кряков", взлома программ и т.д.

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

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


 




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


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

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