Всем привет. Хотел узнать есть ли в ntdll,kernel, ну или в другой библиотека. Функи для работы с хеш таблицами. Пока что пишу свой ми-код с таблицами. Может это лишнее ?
19841204 В экспорте ntdll есть RtlComputeCrc32() и RtlHashUnicodeString(). LdrpCalcResourceChecksum() использует MD5Xx(), но последняя группа не экспортируется. ImportTablepHashCanonicalLists() подгружает advapi32 и использует из неё CryptXx(). В ядре подходящих функций нет. Обычно я использую в юзермоде RtlComputeCrc32(), вначале находя её по имени в экспорте, затем при енуме экспорта целевого модуля для каждого имени вычисляется CRC и сравнивается с целевым. В ядре я поступаю иначе, хеш вычисляется свой для каждого имени, например: Код (Text): xLdrCalculateHash: %GET_CURRENT_GRAPH_ENTRY LdrCalculateHash proc uses ebx esi PartialHash:ULONG, StrName:PCHAR, NameLength:ULONG mov ecx,NameLength mov esi,StrName mov ebx,PartialHash cld @@: lodsb xor ebx,eax xor ebx,ecx rol ebx,cl loop @b mov eax,ebx ret LdrCalculateHash endp
Клерк спасибо за црц но я его уже написал сам Насчет таблиц хешей, неохота вызывать LoadLibrary лишние вызовы, легче самописную юзать
Вообщем сам написал хеш таблицу кому интересно вот. Код (Text): IFNDEF __HASH_TABLE__ __HASH_TABLE equ 1 include crc32.asm .code HTABLE_CTX struct Count dd ? Used dd ? Nodes dd ? AllocFunc dd ? FreeFunc dd ? Crc32 CRC32_CTX <> HTABLE_CTX ends PHTABLE_CTX typedef ptr HTABLE_CTX HTABLE_ENTRY struct Next PVOID ? Key PVOID ? KeySize DWORD ? Data DWORD ? HTABLE_ENTRY ends PHTABLE_ENTRY typedef ptr HTABLE_ENTRY comment ' NTSTATUS AllocFunc(DWORD AllocSizeInBytes,PDWORD AllocationAddress) NTSTATUS FreeFunc(DWORD AllocationAddress) ' ; pCtx - адресс HTABLE_CTX ; pInitialSize - начальное количество свободных елементов ; Return: STATUS_SUCCESS on success, or error status code htable_create proc uses edi pCtx:PHTABLE_CTX,pInitialSize:DWORD,pAllocFunc:PVOID,pFreeFunc:PVOID LOCAL Nodes:DWORD mov edi,pCtx xor eax,eax mov ecx,sizeof HTABLE_CTX rep stosb mov edi,pCtx assume edi:PHTABLE_CTX cmp pInitialSize,0 je _exit mov edx,pAllocFunc lea ecx,Nodes push ecx mov ecx,pInitialSize mov [edi].Count,ecx shl ecx,2 ; BYTE -> DWORD push ecx call dword ptr edx test eax,eax jnz _exit mov ecx,Nodes mov [edi].Nodes,ecx mov eax,pAllocFunc mov [edi].AllocFunc,eax mov eax,pFreeFunc mov [edi].FreeFunc,eax lea ecx,[edi].Crc32 invoke crc32_init,ecx _exit: ret htable_create endp ;VOID htable_destroy proc C uses esi edi ebx pCtx:PHTABLE_CTX LOCAL Item:DWORD LOCAL Counter:DWORD mov edx,pCtx assume edx:PHTABLE_CTX mov ecx,[edx].Count test ecx,ecx jz _exit mov esi,[edx].Nodes _next: mov Counter,ecx lodsd _list: test eax,eax jz _empty assume eax:PHTABLE_ENTRY mov ebx,dword ptr [eax].Next mov Item,ebx push eax mov ecx,dword ptr [eax].Key push ecx call [edx].FreeFunc mov edx,pCtx pop eax push eax call [edx].FreeFunc mov edx,pCtx mov eax,Item jmp _list _empty: mov ecx,Counter loop _next mov edx,pCtx push [edx].Nodes call [edx].FreeFunc _exit: ret htable_destroy endp htable_get_internal proc uses ebx esi edi pCtx:PHTABLE_CTX,pKey:PVOID,pKeySize:DWORD,pAddress:PDWORD LOCAL pCRC:PCRC32_CTX mov edx,pCtx assume edx:PHTABLE_CTX lea ecx,[edx].Crc32 mov pCRC,ecx invoke crc32_final,pCRC invoke crc32_update,pCRC,pKey,pKeySize mov edx,pCtx assume edx:PHTABLE_CTX mov ebx,[edx].Count mov esi,[edx].Nodes xor edx,edx div ebx shl edx,2 add esi,edx lodsd test eax,eax jz _save _next: mov ecx,pKeySize assume eax:PHTABLE_ENTRY cmp dword ptr [eax].KeySize,ecx jne _noequal cld mov esi,[eax].Key mov edi,pKey mov ecx,pKeySize repe cmpsb je _exit _noequal: lea ecx,[eax].Next mov edx,pAddress mov dword ptr [edx],ecx mov eax,[eax].Next test eax,eax jnz _next _exit: ret _save: sub esi,4 mov edx,pAddress mov dword ptr [edx],esi jmp _exit htable_get_internal endp htable_get proc uses ebx esi edi pCtx:PHTABLE_CTX,pKey:PVOID,pKeySize:DWORD,pValue:PDWORD LOCAL pAddress:DWORD invoke htable_get_internal,pCtx,pKey,pKeySize,addr pAddress test eax,eax jz _error mov ecx,pValue assume eax:PHTABLE_ENTRY mov edx,[eax].Data mov dword ptr [ecx],edx xor eax,eax _exit: ret _error: mov eax,STATUS_UNSUCCESSFUL jmp _exit htable_get endp htable_add proc uses ebx esi edi pCtx:PHTABLE_CTX,pKey:PVOID,pKeySize:DWORD,pValue:DWORD LOCAL nKey:DWORD LOCAL pEntry:PHTABLE_ENTRY LOCAL pAddress:DWORD invoke htable_get_internal,pCtx,pKey,pKeySize,addr pAddress test eax,eax jz _notexists assume eax:PHTABLE_ENTRY mov ecx,pValue mov dword ptr [eax].Data,ecx xor eax,eax jmp _exit _notexists: mov edx,pCtx lea eax,pEntry push eax push sizeof HTABLE_ENTRY call [edx].AllocFunc test eax,eax jnz _exit mov edx,pCtx lea eax,nKey push eax push pKeySize call [edx].AllocFunc test eax,eax jnz _free mov esi,pEntry assume esi:PHTABLE_ENTRY mov ecx,nKey mov dword ptr [esi].Key,ecx mov ecx,pKeySize mov dword ptr [esi].KeySize,ecx mov dword ptr [esi].Next,eax mov ecx,pValue mov dword ptr [esi].Data,ecx cld mov esi,pKey mov edi,nKey mov ecx,pKeySize rep movsb ;add to list mov eax,pAddress mov ecx,pEntry mov dword ptr [eax],ecx mov edx,pCtx inc [edx].Used xor eax,eax _exit: ret _free: push eax mov edx,pCtx push pEntry call [edx].FreeFunc pop eax jmp _exit htable_add endp ENDIF Эт црц Код (Text): IFNDEF __CRC32__ __CRC32__ equ 1 CRC32_CTX struct Hash dd ? Table dd 256 dup (?) CRC32_CTX ends PCRC32_CTX typedef ptr CRC32_CTX .code crc32_init proc uses esi edi pCtx:PCRC32_CTX xor ecx,ecx xor edx,edx add ecx,256 cld mov edi,pCtx lea edi,[edi + CRC32_CTX.Table] _next: mov eax,edx mov esi,8 _inner: shr eax,1 jnc @f xor eax,0EDB88320h @@: dec esi jnz _inner stosd inc edx loop _next mov edi,pCtx assume edi:PCRC32_CTX xor eax,eax mov dword ptr [edi].Hash,eax ret crc32_init endp crc32_update proc uses ebx esi edi pCtx:PCRC32_CTX,pBuffer:PVOID,pBufferSize:DWORD mov esi,pBuffer mov ecx,pBufferSize mov edi,pCtx assume edi:PCRC32_CTX mov edx,[edi].Hash lea edi,[edi + CRC32_CTX.Table] not edx cld @@: test ecx,ecx jz _end lodsb mov ebx,edx and ebx,0FFh xor bl,al shr edx,8 and edx,0FFFFFFh shl ebx,2 ; byte to dword offset xor edx,dword ptr [edi+ebx] ;xor edx,0D202EF8Dh dec ecx jmp @B _end: not edx mov edi,pCtx assume edi:PCRC32_CTX mov [edi].Hash,edx xchg edx,eax ret crc32_update endp crc32_final proc pCtx:PCRC32_CTX mov ecx,pCtx assume ecx:PCRC32_CTX mov edx,dword ptr [ecx].Hash xor eax,eax mov dword ptr [ecx].Hash,eax xchg eax,edx ret crc32_final endp crc32 proc pBuffer:PVOID,pBufferSize:DWORD LOCAL ctx:CRC32_CTX invoke crc32_init,addr ctx invoke crc32_update,addr ctx,pBuffer,pBufferSize invoke crc32_final,addr ctx ret crc32 endp ENDIF Как юзать пример Код (Text): ;for debug only!!! MmAlloc proc uses ebx esi edi pAllocSizeInBytes:DWORD,pAllocBuffer:PDWORD invoke LocalAlloc,LPTR,pAllocSizeInBytes test eax,eax jnz _success mov eax,STATUS_NO_MEMORY jmp _exit _success: mov edx,pAllocBuffer mov dword ptr [edx],eax xor eax,eax _exit: ret MmAlloc endp ;for debug only!!! MmFree proc uses ebx esi edi pMem:DWORD invoke LocalFree,pMem ret MmFree endp invoke htable_create,addr ctx,4,MmAlloc,MmFree invoke htable_add,addr ctx,chr$("test1"),5,1 invoke htable_add,addr ctx,chr$("test2"),5,2 invoke htable_add,addr ctx,chr$("test3"),5,3 invoke htable_add,addr ctx,chr$("test4"),5,4 invoke htable_get,addr ctx,chr$("test2"),5,addr temp invoke htable_destroy,addr ctx Как понимаете стиль юза написан попростому. В реале там должен быть ми-код
19841204 Во первых вы не сказали конкретно задачу/цель использования хешей. Во вторых загрузка и вызов функции из модуля увеличит размер кода не значительно(+5/6 байт на хеш имени апи и пара десятков байт на загрузку модуля). Вдобавок вы во всех своих топиках говорите что пишите мутирующий код, тогда я и не знаю как быть на счёт хотябы этого: Код (Text): lea edi,[edi + CRC32_CTX.Table] Какой размер кода, генерирующего эту таблицу, 0xFF*(4 + OpSize), в лучшем случае более килобайта ? Вызов: Код (Text): invoke LocalAlloc,LPTR,pAllocSizeInBytes test eax,eax jnz _success mov eax,STATUS_NO_MEMORY можно считать кривым, так как вы смешиваете ядерные статусы с пользовательскими функциями, следует не использовать виньапи, либо получать статус и возвращать его.
Код (Text): lea edi,[edi + CRC32_CTX.Table] Вы правы я пишу мутирующий код, но по идее можно морфнуть эту инстуркцию как add edi,CRC32_CTX.Table. Я вроде правильно понимаю. Так как оффсет полей статичен. Вы же тоже пишете mov eax,dword ptr fs:[TEB.Peb] Ну вы правы, но память выделается именно при работе программы. Поэтому сам файл не будет на 0xFF*(4 + OpSize) больше. Это понятно, то есть я навязываю статус код свой. Если говорит чесно то при выделении памяти мне вообще по барабану. Какой статус код ошибки будет. Мне важней знать есть память или нет. LocalAlloc->HeapAlloc и согласно доке чтобы получить статус код надо установить атрибут прияма ексептионов иначе никак. Но так как там всего 2 статуса, я решил поставить свой Эта офф дока.
Я создаю PE builder, тоесть мой зверек должен превращать себя из екзе в длл, и плюс к ютому добавлять експорт и импорт. Exe->Dll , там поля всего нужно подправить IMAGE_NT_HEADERS32.OptionalHeader.Characteristics. А вот в свое тело добавить импорт и експорт это уже посложней будет С этим я полностью согласен. Просто я и незнал что в ntdll уже есть crc32
19841204 Мутирующий код не может содержать данных. Если они есть, то код не мутирующий, а будет пересобран пермутатором на основе описателей данных(фиксапы и прочие дефины). Регистр Fs адресует страницу с системным окружением. База сегмента не фиксирована, а адресуется сегментным регистром, в оличае от непосредственных ссылок на данные(0:Offset). Для сегментов с нулевой базой виртуальный адрес равен смещению в сегменте. Самое сложное определить фиксапы, которых обычно в екзе нет, но должны быть в длл.
Крерк это понятно но там нету данных, там в edi указатель на данные. Причем после мутации. Код сгенерирует данные вновь. Так и не понял где там ошибка. В висте и семерке уже есть там же ASLR. Я просто хочу создать нулевую длл. Сделать фейковые секции. Запихнуть туда свой ми-код. И добавить импорт и экспорт.
Для быстрой обработки файла. Чтобы не по списку бежать и смотреть адресс експорта, а сразу через хеш таблицу получить. Это быстрее когда, когда всего много. Плюс я еще хотел для knowsdll проверять библиотека лежит там или нет. Вместо каждого вызова функций. Вообщем все для скорости и все Да к стате к кому стучать чтобы мне ник можно было сменить? 19841204 задолбал уже
19841204 Наоборот медленнее, чем просто имена сравнивать, так как для каждого имени необходимо вычислить хеш.
19841204 Вам последнее предупреждение. По теме: посмотрел вики и не знаю в таком случае что вам нужно и причём тут экспорт.
Да клерк не обежайся Ладно пробую обьяснить. Меня не интересуют хеш функции md5,md4,..., то есть не обратимое хеширование. Меня интересуют хеш таблици. Доступ к елементу хеш таблици выполняется за короткое время и совсем не важно большая эта таблица или нет. В том и достигается производительность, что найти елементы в 10 GB можно очень быстро. Вот меня и интересует, может ктото это уже реализовал. Но ответов не было поэтому я взял сорсы сфинкса. Есть такой поисковый демон. И перевел его на асму, вот и все. Меня интересует вообще на будущее. Может хеш таблицы уже есть в ком компонентах. Я видел в win7 есть RtlCreateHashTable, в других не видел. Я так понял никто их в нашем деле не использует. ну да ладно.
В WDK есть функции для работы с деревьями, в том числе AVL. http://msdn.microsoft.com/en-us/library/ff552989(v=VS.85).aspx
> Мутирующий код не может содержать данных. Если они есть, то код не мутирующий, а будет пересобран пермутатором на основе описателей данных(фиксапы и прочие дефины). Щито? Доставляет кусок фразы "код не может содержать данных" - таки да, курица обычно не содержит яиц (по крайней мере пока они внутри курицы, они яйцами не называются). Или я гоню? Действительно, если код перемешан с данными (шелкодес, или тот же eicar), то пытаться его мутировать это полная жопа. Но, код, который использует данные можно прекрасно морфить, если не трогать данные. Как пруф - почти всегда корректная работа виртуализаторов типа ExeCryptor'а или VMProtect'а. Даже на бинарях без релоков. На асмовой мешанине они скорее всего профейлятся, но на HLL по шаблонам прекрасно отличают от кода всякие switch таблицы или блоки try/except/final (развивались долго,да, но факт что таки можно =) И это уже на бинарном уровне. Я боюсь заикаца про пермутаторы уровня сорцов - тупейший перловый скрип, превращающий все mov eax, offset table в mov eax, offset table-666 lea eax, [eax+666] выносит мозг той же IDA Pro вместе с хакером и всеми кросрефами
> Для быстрой обработки файла. Чтобы не по списку бежать и смотреть адресс експорта Имена в таблицае экспорта бинарно отсортированы, так что выигрышь от хэшмапа тут хоть и есть, но сомнителен. > В том и достигается производительность, что найти елементы в 10 GB можно очень быстро. Практика показала штаа на х86 (и х64 естесно) хэшмап больше 2мб становится весьма неэффективным - постоянно выбивает кэши проца. Так что 10гб я могу допустить только разве что там будут сплошные нули. Для реальных данных - 100к узлов. Дальше лучше использовать таки деревья - если данные поиска статичный то AVL деревья, если динамические - то red-black