> Я все проверил - работает ... 8 ) , причем как с > инициализированными ('DATA'), так и не с > инициализированными данными ('BSS'). > Не ожидал я такого результата. Странно все это ... нужно > переворить ... ;)
Дело здесь в том, видимо, что Винда помечает дескриптор сегмента cs как начинающийся с адреса 400000 и заканчивающиеся адресом FFFFFFFF, поэтому может выполняться код, находящийся по любому адресу в этом диапазоне. А то, что этот код записан в эти адреса через дескриптор ds - ось уже не волнует... :)
> > Приятно было пообщаться и извини за нелестный отзыв о твоем > коде.
А код был правильный и очень грамотный - и ассемблерный и сишный. Давно такого лаконичного и красивого кода не встречал (в смысле, что он точно комментирует тему, поднятую в обсуждении). За это отдельное спасибо г-ну z0.
правильно тебе пишет ggg - на си это самый правильный способ
единственное что меня повлекло на этот мессаг - это момент джампа
если ты линкуешь эти проги одновременно - все зашибись, тот джамп про который говорил ggg делаешь екстерном
а вот в противном случае я бы сделал ДВЕ дллки
потому что работать в момент DLL_INIT вообще говоря не очень хорошо, лучше так:
рабочий кусок - функцией в первой длл и инит у нее стандартный
во вторую длл импортируешь ту функцию из первой и вызываешь ее в момент DLL_INIT первой длл
вторую длл грузишь через LoadLibrary и никаких джампов не надо
так будет работать железно
[C++] Выполнение кода программы19.01.02 22:01 Автор: ih8u <i hate you> Статус: Member
Мля, вы навена не правильно поняли,
есть прога моя, и прога другая,
я в своей проге открываю другую,
считываю всё, и нада её запуситть,
или вариант- эту вторую прогу держать в себе,
гденить в конце моей проги дописать,
причом сделсь loadlibrary ??
[C++] Выполнение кода программы20.01.02 20:10 Автор: z0 <z0> Статус: Member
> есть прога моя, и прога другая, > я в своей проге открываю другую, > считываю всё, и нада её запуситть,
это один вариант. здесь можно exec() {читай CreateProcess()} - зачем открывать считывать etc?
> или вариант- эту вторую прогу держать в себе, > гденить в конце моей проги дописать,
а это второй принципиально другой
еще процитирую из первой твоей мессаги важный момент:
>> в buf будет прога как вы поняли,
>> вот её надо выполнить,
>> причом без способов типа скинуть на диск и запустить,
>> реально ли такое?
или третий вариант который напрашивается поскольку ты же не зря наверное пишешь об открытии-считывании - твоя "вторая прога" как-то пошифрована etc
> причом сделсь loadlibrary ??
LoadLibrary здесь при том что она умеет за тебя выполнить кучу работы по запуску проги - загрузку секций, релокейшины, привязку к импортам-экспортам и это все в контексте твоей первой проги т.е. давая твоей первой проге простой доступ к к этой "ДЛЛ" и отрабатывая только DLL_INIT который легко воткнуть свой пустой куда нибудь в SECTION_ALIGN и надо только слегка подправить хедер чтобы прога загрузилась как ДЛЛ через LoadLibrary
так вот для второго твоего способа где ты хочешь хранить в одном екзешнике другой и не сбрасывать на диск перед запуском этот кусок тебе НЕ ПОМОГУТ ни LoadLibrary ни CreateProcess - здесь надо грамотно врезать одну прогу в другую и запускать через обычный джамп
PE формат такие фокусы разрешает
что конкретно здесь надо сделать:
1) хедер второй объединить с хедером первым
2) импорты объединить в одну таблицу
3) перенести RVA секций второго екзешника в удобное место и соответственно изменить фиксапы
4) фиксапы объединить в одну таблицу
5) в первой проге jmp/call второй проги поставить правильным адресом (см. п.3)
6) допустим экспортов нет ни в одной
так можно хоть 20 прог слить вместе
ты старайся сразу конкретно рассказывать а то тебя и вправду понять трудно
[C++] Выполнение кода программы21.01.02 00:23 Автор: ih8u <i hate you> Статус: Member
> интересно, а как эгзе-пакеры распаковывают и запускают > прогу?, вроде там тоже должен быть загрузчик начальный
Ехе-пакеры работают так:
1. ОС грузит экзешник в память.
2. Точка запуска у него (екзешника) не стандартная, 0х400000, а где-нибудь в старших адресах.
3. Запускается встроенный распаковщик, он распаковывает екзешник в нижние адреса (обычно начиная с 0х400000).
4. В соответствии с таблицей релокейшенов меняет в памяти адреса
5. Потом делает джамп на точку старта езешника.
В твоем случае основная трудность будет в том, что буфер под загружаемый файл выделяется не в cs сегменте, а в ds сегменте. А в защищенном режиме запуск кода возможен только из cs сегмента. Так что тебе надо менять параметры дескриптора сегмента памяти ds, чтобы разрешить выполнение кода в нем.
[C++] Выполнение кода программы21.01.02 18:43 Автор: z0 <z0> Статус: Member
> А в защищенном режиме запуск кода возможен только > из cs сегмента.
ну блин не могу
1) для флат-режима страницы видны одинаково и по CS-у и по DS-у
2) защиты страницы от исполнения не существует
3) значит можно код держать в любом месте - хоть на стеке - ты только не говори никому что это DS/SS а говори что это CS и все зашибись
PS: твое утверждение справедливо для WIN3.X кстати
PPS: а вот защита от записи есть на уровне страницы и тут-то и могут быть проблемы но уже другого плана - например как вручную сделать релокейшины - и если память не пишется решение как раз в том чтобы грузить код ИМЕННО в область данных т.е. в DS сегмент загрузчика/распаковщика
ih8u: что ты так мучаешься - возьми любой запакованный екзешник и разберись один раз и навсегда как оно работает
[C++] Речь идет о ring3 или ring0 ?23.01.02 02:36 Автор: LiNX Статус: Незарегистрированный пользователь
> 1) для флат-режима страницы видны одинаково и по CS-у и по > DS-у > 2) защиты страницы от исполнения не существует > 3) значит можно код держать в любом месте - хоть на стеке - > ты только не говори никому что это DS/SS а говори что это > CS и все зашибись > Можно попросить описать (на словах) или выложить код на основании которого были сделаны данные выводы ? + Под какую ось и версию виртуальной машины (если она используется).
ЗЫ: так как согласно документации такой номер пройти не может.
[уже не C++ сори ;-))] по фигу какой ринг в данном акцепте23.01.02 12:41 Автор: z0 <z0> Статус: Member
> > 1) для флат-режима страницы видны одинаково и по CS-у > и по > > DS-у > > 2) защиты страницы от исполнения не существует > > 3) значит можно код держать в любом месте - хоть на > стеке - > > ты только не говори никому что это DS/SS а говори что > это > > CS и все зашибись > > > Можно попросить описать (на словах) или выложить код на > основании которого были сделаны данные выводы ? + Под какую > ось и версию виртуальной машины (если она используется). > > ЗЫ: так как согласно документации такой номер пройти не > может.
меня ТА документация не трахает
смотри
;--------------------------------- test.asm -------------------------------------------
.386
extrn MessageBoxA :near
extrn ExitProcess :near
code32 segment use32 para private 'code'
assume cs:code32
assume ds:data32
> > > 1) для флат-режима страницы видны одинаково и по CS-у и по DS-у Конечно видны, ведь есть селекторы сегментов (CS и DS) ,- но ты в данном контексте утверждаешь, что не существует защиты сегментов на уровне МП от перезаписи и исполнения ...
> > > 2) защиты страницы от исполнения не существует Исполняются не страницы, а сегменты. Один и тот же участок памяти может одним дескриптором описываться как код и управляться через (CS) , а другим как данные и управляться через (DS) - на этом баге может быть построена и некоторая виртуальная машина, при этом исполнение МП производит всегде через CS (говри-неговори), плюс к этому и дескриптор сегмента должен быть помечен как "исполняемый" - эти два условия позволяют выполинть код.
> > > 3) значит можно код держать в любом месте - хоть на стеке - ты только не говори никому что это DS/SS а говори что это CS и все зашибись Код действительно можно держать где угодно, но чтобы сегмент через один и тот же дескриптор (а дескриптор, это совсем не тоже самое, что CS/SS/DS) можно было и исполнять и читать - не реализовано в МП.
> меня ТА документация не трахает ТА документация это описание процессоров INTEL
ЗЫ: Если даже тебе и удастся самому собрать оба домашних задания, это все равно не подтвердит ни один из 3 пунктов.
[возвращаемся на C] код кривой?24.01.02 14:14 Автор: z0 <z0> Статус: Member
ни фига себе! код кривой? где? покажи пальцем
собрать не удается? хорошо допустим на асме мало кто умеет работать под винду вот тебе на си аналог этот-то я надеюсь соберешь
------------------------------------ test.c -------------------------------------
#include <stdio.h>
#pragma push (check_stack)
#pragma off (check_stack)
void some_function(void)
{
int (*printf_indirect)(const char*,...)=&printf;
printf_indirect ("hello from data section!\n");
return;
}
#pragma pop (check_stack)
void some_next_function(void) {}
void main(void)
{
int size_of_function = (int)(&some_next_function) - (int)(&some_function);
int i;
void (*this_we_call)(void) = (void (*)(void)) code_in_data_section;
> а что там ему может не понравиться? прагмы? так посмотри в > доке - смысл там прост - отключить генерацию вызова > __chkstk() в прологе Da pragm push and pop netu
[забудь про C] С только путает здесь24.01.02 20:37 Автор: LiNX Статус: Незарегистрированный пользователь
1. То, что DOS-ие TINY проги творят чудеса в ... DOS-е я знал давно ;)
2. Ассемблерный код "не понравился мне (и компилятору)" от "а" до "я" - одно то, что используется допотопная лексика назначения сегментов ... , а то, что экзешник можно и в "Блокноте" слепить ... [не для обсуждения]
3. Заставь свой BORLAND C сгенерировать ассемблерный код и посмотри: подпрУга, которую ты стараешься запихнуть неизвестно куда случайно не в сегменте с именем _TEXT .... 'CODE' (assume cs:_TEXT) окажется и не будет ли она вызываться как и остальные ;)
ЗЫ: Ты так уверено жонглируешь исходниками, что я уже начинаю сомневаться в своей правоте ;)
[забудь про C] С только путает здесь25.01.02 07:27 Автор: z0 <z0> Статус: Member Отредактировано 25.01.02 07:52 Количество правок: 1
> 1. То, что DOS-ие TINY проги творят чудеса в ... DOS-е я > знал давно ;)
при чем тут это? какие проги, какие чудеса, какой DOS
ты чего имеешь в виду test.c ???
я его делал как консольное приложение и проверял/отлаживал на NT4 & W98
хотя вообще-то он в досе тоже должен работать (перекомпилированный)
> 2. Ассемблерный код "не понравился мне (и компилятору)" от > "а" до "я" - одно то, что используется допотопная лексика > назначения сегментов ... , а то, что экзешник можно и в > "Блокноте" слепить ... [не для обсуждения]
скажи какой ассемблер - линкер ты использовал (например TASM 4.1 + TLINK 7.3.10.1) и я тебе под него дам неконфликтный исходник и батник-построитель
что такое "допотопная лексика назначения сегментов" ?
даже интересно стало
и что такое "недопотопная" кстати
это когда пишут .code .data etc ???
ты это серъезно ???
> 3. Заставь свой BORLAND C сгенерировать ассемблерный код и > посмотри: подпрУга, которую ты стараешься запихнуть > неизвестно куда случайно не в сегменте с именем _TEXT .... > 'CODE' (assume cs:_TEXT) окажется и не будет ли она > вызываться как и остальные ;) >
доказываю что как ты выразился "подпрУга" находится в сегменте данных
смотри:
------------------------------------ test.map-----------------------------------------
WATCOM Linker Version 11.0
Copyright by Sybase, Inc., and its subsidiaries, 1985, 1997.
Created on: 02/01/25 07:10:47
Executable Image: test.exe
creating a Windows NT character-mode executable
+------------+
| Groups |
+------------+
Group Address Size
===== ======= ====
.idata 00408000 00000608
DGROUP 00409000 000128c0
+--------------+
| Segments |
+--------------+
Segment Class Group Address Size
======= ===== ===== ======= ====
BEGTEXT CODE AUTO 00401000 00000007
_TEXT CODE AUTO 00401010 00006149
TRANSFER CODE CODE AUTO 0040715c 0000014a
.idata .idata .idata 00408000 00000608
_NULL BEGDATA DGROUP 00409000 00000004
_AFTERNULL BEGDATA DGROUP 00409004 00000000
CONST DATA DGROUP 00409004 000005e4
CONST2 DATA DGROUP 004095e8 00000000
_DATA DATA DGROUP 004095e8 000008a9
YIB DATA DGROUP 00409e92 00000000
(skipped by [z0] - too large)
TIE DATA DGROUP 00409ec2 00000000
DATA DATA DGROUP 00409ec2 00000000
_BSS BSS DGROUP 0040a010 000018a8
STACK STACK DGROUP 0040b8c0 00010000
Stack size: 00010000 (65536.)
Memory size: 0001916e (102766.)
Entry point address: 004010d0
Link time: 00:00.83
> ЗЫ: Ты так уверено жонглируешь исходниками, что я уже > начинаю сомневаться в своей правоте ;)
правильно сумневаешься
единственное правильное утверждение твое было - "процессор использует регистр CS и его дескриптор для исполнения кода"
впрочем к чему оно было нам сообщено - непонятно
а я на тебя обижен - мой код назвать кривым !!!
[забудь про C] С только путает здесь25.01.02 23:32 Автор: LiNX Статус: Незарегистрированный пользователь
Я все проверил - работает ... 8 ) , причем как с инициализированными ('DATA'), так и не с инициализированными данными ('BSS').
Не ожидал я такого результата. Странно все это ... нужно переворить ... ;)
Приятно было пообщаться и извини за нелестный отзыв о твоем коде.
[забудь про C] извинения приняты26.01.02 08:11 Автор: z0 <z0> Статус: Member
понимаю тебя в каком-то смысле - ты же был УВЕРЕН что прав
никогда не доверяй документации - много вранья и полуправды - ИМ НЕ ВЫГОДНО ЧТОБ ТЫ ЗНАЛ, А ВЫГОДНО ЧТОБ УМЕЛ И ИМЕННО ТО ЧТО ИМ НАДО - все надо проверять самому
"хакер" и "юзер" , понимаешь?
[забудь про C] С только путает здесь26.01.02 00:38 Автор: Sandy <Alexander Stepanov> Статус: Elderman
> Я все проверил - работает ... 8 ) , причем как с > инициализированными ('DATA'), так и не с > инициализированными данными ('BSS'). > Не ожидал я такого результата. Странно все это ... нужно > переворить ... ;)
Дело здесь в том, видимо, что Винда помечает дескриптор сегмента cs как начинающийся с адреса 400000 и заканчивающиеся адресом FFFFFFFF, поэтому может выполняться код, находящийся по любому адресу в этом диапазоне. А то, что этот код записан в эти адреса через дескриптор ds - ось уже не волнует... :)
> > Приятно было пообщаться и извини за нелестный отзыв о твоем > коде.
А код был правильный и очень грамотный - и ассемблерный и сишный. Давно такого лаконичного и красивого кода не встречал (в смысле, что он точно комментирует тему, поднятую в обсуждении). За это отдельное спасибо г-ну z0.