· Начало · Отвђтить · Статистика · Поиск · FAQ · Правила · Установки · Язык · Выход · WASM.RU · Noir.Ru ·

 WASM Phorum —› WASM.A&O —› "Оптимизация" таблицы импорта. Импортируем dll при загрузке

Посл.отвђт Сообщенiе


Дата: Фев 9, 2004 08:18:47 · Поправил: S_T_A_S_

Привет всем!
(не хотелось бы обсуждать приимущества/недостатки различных извратов с таблицей импорта)

В общем, делаю я таблицу импорта - там только одна функция - GetProcAddress.
Имена остальных - массив ascii строк, заканчивающихся нулями в таком формате:


IMPORTED_NAMES:
db "имя proc из kernell.dll",0
.....
db "имя proc из kernell.dll",0
db 0 - конец списка функций для dll
db "имя *.dll",0
db "имя proc из *.dll",0
.....
db "имя proc из *.dll",0
db 0FFh - конец таблици


Далее написал такой код, который этот список обрабатывает при запуске программы. Сейчас он весит 65 байт (если метка ..ENTRY_POINT не далеко). Но в таких случаях хочется меньшего. Какие-нибудь идеи?

Может саму таблицу по другому организовать? (CRC32 для имен я использовать не хочу, по той же причине, как и поиск kernel32 через стек)



Это FASM, но думаю все понятно:
__RTImportLibraries:
		mov		EBX,	[GetProcAddress$$]	;; this function IS inside the kernel32.dll
		mov		EBP, EBX
@@:		xor		BX,	BX				;; dlls are loaded at addresses XXXX0000h, so align
		cmp		word	[EBX], 'MZ'		;; check first 2 bytes of PE
		jz		@f					;; Kernel32.dll found
		dec  	EBX					;; search backward. Now -1, ^^ align by 10000h
		jmp		@b
;; here we have got handle to module kernel32.dll in EBX. Really, I like word "address"
@@:		cld
		mov		EDI, IMPORTED_NAMES
		mov		ESI, LOCKUP_TABLE
@@:		stdcall	EBP, EBX, EDI			;;  invoke GetProcAddress
		mov		[ESI], EAX			;;  store it in Locup Table
		add		ESI, 4
;;  search next imported name
.s:		xor		Al, AL
		mov		ECX, EDI		;;  well, I'm sure strings won't be so big
		repnz	scasb		;;  find next string
		cmp		[EDI], AL
		js		..ENTRY_POINT	;;  end of table found, start the programm
		jnz		@b			;;  proc name found
;;  if we are here, new dll name is found
		inc		EDI
		invoke	LoadLibrary, EDI
		mov		EBX, EAX		;;  new dll base address
		jmp		.s	



ЗЫ
Это работает в 98, XP и некоторых 2к. В других не тестировал. Вот пример exe (оптимизирован похуже)


Дата: Фев 9, 2004 08:52:59

Вот пример (оптимизирован похуже)
на моей 98 выполняет недопустимую операцию...

А основной вопрос непонятен. Что мешает таблицу пожать?


Дата: Фев 9, 2004 09:14:57

Да, можно и CRC вычислять, но тогда сама процедура увеличится. Так что тут вопрос, когда будет выигрыш.
Еще, таблица имен строится простым макросом в FASM. А как я буду ее "пожать" на этапе компиляции?

К тому же я пытаюсь использовать ТОЛЬКО документированные приемы (ну, или те которые могут быть к ним приравнены). Маловероятно, что MS будет запускать процесс jmp, но мне в данном случае - все равно, в отличае от поиска кернела через стек.

Так что основной вопрос - уменьшение самой процедуры импорта (ну может еще 0-ли уберу в концах строк)
Поэтому у меня "оптимизация" в кавычках :)

(хотя вообще-то, что-то плохо стало с русским)

на моей 98 выполняет недопустимую операцию...
Возможно, по команде movntq? У меня вот работает на SE..


Дата: Фев 10, 2004 21:12:55

S_T_A_S_

Это тот случай, когда надо заниматься низкоуровневой оптимизацией. Пожать таблицу можно - для этого достаточно в исходники поместить ее уже пожатой в hex-формате - это можно сделать с помощью либо своей программы, либо сторонней утилиты. Можно и имена хеш-функцией пожать, но и в первом, и во втором случае придется писать код. Я бы использовал ординалы и не парил себе мозги.


Дата: Фев 10, 2004 22:22:15

Самый главный вопрос здесь: каков смысл всего этого? Если только "оптимизировать"
таблицу импорта, то все равно больше 65 байт не сэкономить :) ст0ит ли свеч?
А если уменьшить обьем целевого бинарника, то заниматься надо сжатием всей программы...


Дата: Фев 11, 2004 03:28:04

Я согласен, что надо заниматься сжатием всего PE, что бы получить экономию. В таком случае можно рассматривать мои 65 байто в как код, который будет обрабатывать распакованные секции.. и т.д и т.п. - но это другой вопрос


Я вот получил 65 байтов, оригинал был несколько больше и юзал ESP.
И мне интересно: можно ли сделать еще меньше? И как??

Если меньше нельзя, то положу макросы, которые автоматизирует создание этой лабуды в FASM. Используются вместо "стандартных" library / import. Кому-то может и пригодится, что-бы руками не липить


volodya

Ординалы, возможно, не всегда хорошо. ( Потом, как мне их FASM выдаст? Ручками считать? )
Хотя с другой стороны модификация будет не большая, если их использовать :)


Дата: Май 22, 2004 05:44:20

круче Харона импорт никому не оптимизировать!
расковыряйте ulink - найдете много интересного (ftp://ftp.styx.cabel.net/pub/UniLink/)

а еще есть BOUND IMPORT - он быстрее всех, т.к. при нем библиотека просто проецируется и усе. а эффективные адреса прописываются еще на стадии компиляции, однако, версия DLL должна быть известна наперед.

как вариант можно заюзать DELAY IMPORT, правда, зачастую он дает тормоза, а не ускорение, так что юзать его надо с умом...

плюс еще можно загнать в IAT копию INT - на XP это ускоряет загрузку файла, остальные об этой фиче не знают...

да много разных вариантов, словом...


Дата: Май 22, 2004 22:19:19

Да, вариантов разных много. Навязчивая идея была ипользовать только документированные возможности ОСи, чтобы не появились обломы, если моя прога будет запускаться не CALL, а JMP. Или МС вдруг не поменяет ординалы.


Дата: Май 22, 2004 22:48:35


но мне в данном случае - все равно, в отличае от поиска кернела через стек.

А нахрена?
Ты уже линкуешься с кернелом (GetProcAddress) Кто мешает тебе плясать от GetProcAddress, а не через стек?

Ординалы - нахерн.. нахрен.. Не гарантировано это.

p.s. для сишных, которые не надо upx-ить добавляю ещё так :
#pragma comment(linker, "/FILEALIGN:2 /SECTION:.text,EWRX /IGNORE:4078")
В результате порядка 10-20К экономии.


Дата: Май 22, 2004 22:59:44

> Ты уже линкуешься с кернелом (GetProcAddress) Кто мешает тебе плясать от GetProcAddress, а не через стек

Дык.. я так и делаю :-)


Дата: Май 23, 2004 01:46:34

Интересно, вот тут зашел вопрос об aline'е секций, мне стало интересно, я копнул fasm, но не нашел там опций для выравнивания секций, в fasm'е можно это сделать?, не используя линкер?


Дата: Май 23, 2004 05:35:45

копайте ulink ;)
1) для своих библиотек _всегда_ используйте bound import, быстрее его ничего не бывает;

2) для библиотек ядра пишите свой GetProcAddress (если надо, я подкину сырец движка, сырой, правда, но работающий). смотрите - имена фунций всегда отсортированы по алфавиту, поэтому поиск нужной функции резко ускоряется (метод вилки), к тому же можно зарелизить функцию, импортирующую за раз много-много экспортов. ну зачем каждый раз делать разбор INT с начала? сортируем свои функции по алфавиту - и проходим экпорт всего однин раз (да и того с учетом вилки не будет). короче говоря, вполне реально получить стократное ускорение, не рискуя при этом разорвать себе задницу.


Дата: Май 23, 2004 14:01:25

2rst

Ага тока ДЛЛ при такой компиляции запускаться не будет +) минимум это FILEALIGN:512 ...

Хотя может кто то знает какой то волебный способ заставить работать и так,?


Дата: Май 23, 2004 21:41:29

[ jekyll : AFAIK - копнул fasm, но не нашел там опций для выравнивания секций, в fasm'е можно это сделать? ]

AFAIK, используя стандартный форматер (директива format) - нет.
Но можно написать весь заголовок через DB/DD (без format) и получить любое выравнивание.


Powered by miniBB 1.6 © 2001-2002
Время загрузки страницы (сек.): 0.355