RCE.SU - реверсинг, кодинг, выделенные сервера, ICQ, proxy

Original Entry Point Finding

[Исследование]

Subject: Educational Purpose.
Target: Any VC++ programm.
URL:www.microsoft.com.
Author: aSL!
Date: 14.07.2001

Before starting!
Все ниже изложенное предназначено только для образовательных целей.

I. Вступление

Здравствуйте мои маленькие любители прекрасного! :)

Вы, наверное, помните, что я обещал открыть целый цикл статей про нахождение OEP без отладчика. Помните? Вот и ладненько... И как успехи? Ну ладно, давайте же займемся этим вплотную...

II. Постановка задачи
  1. Необходимо найти OEP у программы, написанной на VC++.
III. Исследование

Необходимые инструменты:

  1. IDA 4.x
  2. libc.lib из комплекта VC++. У меня будет от шестых.

Итак, приступим...

Что мы имеем. Я взял и написал простенькую Win32 программулину на сях. Исходники ее весьма и весьма сложны :))):

#pragma comment(linker,"/FILEALIGN:512 /MERGE:.rdata=.text /MERGE:.data=.text /SECTION:.text,EWR /IGNORE:4078")

int main(void)
{
return 0;
}

Сразу же вопрос: а зачем такая #pragma? Ответ: так я говорю линкеру, что неплохо было бы нашему файлику иметь все в одной секции: экономия на место, однако.
После компиляции выходной .exe получился весьма и весьма большим. (Все настройки были по дефолту). К чему я это: Естественно, напрашивается вопрос: а почему? Конечно, как и в случае с делфями тут компилер приделывает туевую хучу своих .lib'ов. Взглянем-ка мы на "Project ->Project Options ->Link -> Object/Library modules". Увидали сколько их всех? Стираем их всех нафиг. Также не забываем поставить галку "Ignore default libraries". Нечего что-то там прилинковывать без нашего участия. Сделали?
Жмем на "Rebuild all". Тут нас линкер и обматерил, что:

LINK : error LNK2001: unresolved external symbol _mainCRTStartup

Угу... Что-то мне подсказывает, судя по названию, что тут-то и собака зарыта :) Почему? Да просто этот код встречается в дефолтных библиотеках типа libc.lib сотоварищи. Нашли эту строчку там? И мне кажется, что именно эта гадость и вызывается где-то в начале. Добавим libc.dll к списку используемых библиотек. Опять давим "Rebuild all". Хм... Судя по именам, что-то он хочет из кернеля вызвать, да не может. Добавим kernel32.lib. О-па! Скомпилировалось. Ну что ж... Будем копать libc.lib.

Для этих целей нам понадобится еще lib.exe из состава VC++. Запускаем (для удобности скопировав в отдельную директорию lib.exe и libc.lib):

LIB.EXE /LIST LIBC.LIB>1

Получаем длинююююющий список всех .obj, что запрятаны в .lib. Какая же из них наша. Что-то мне подсказывает, что она должна иметь crt и имени. Таких набралось не так-то много. Начнем. Первой я попробую crt0init.obj. Что-то имя мне это нравится...

LIB.EXE /EXTRACT:build\intel\st_obj\crt0init.obj LIBC.lib

Посмотрим туда. Нет. А зря :) Смотрим дальше. Я выбрал crt0.obj. (Приложение не оконное и wincrt0.obj мне что-то не нравится :)))

LIB.EXE /EXTRACT:build\intel\st_obj\crt0.obj LIBC.lib

Смотрим вовнутрь. Опа! Она. Загружаем ее в IDA. Получаем следующий листинг:

public _mainCRTStartup
_mainCRTStartup proc near

var_20 = dword ptr -20h
var_1C = dword ptr -1Ch
var_18 = dword ptr -18h
var_14 = dword ptr -14h
var_4 = dword ptr -4

push ebp
mov ebp, esp
push 0FFFFFFFFh
push offset $T17244
push offset __except_handler3
mov eax, dword ptr fs:__except_list
push eax
mov dword ptr fs:__except_list, esp
sub esp, 10h
push ebx
push esi
push edi
mov [ebp+var_18], esp
call dword ptr ds:__imp__GetVersion@0
xor edx, edx
mov dl, ah
mov dword ptr ds:__winminor, edx
mov ecx, eax
and ecx, 0FFh
mov dword ptr ds:__winmajor, ecx
shl ecx, 8
add ecx, edx
mov dword ptr ds:__winver, ecx
shr eax, 10h
mov dword ptr ds:__osver, eax
push 0
call __heap_init
pop ecx
test eax, eax
jnz short loc_0_7F
push 1Ch
call _fast_error_exit
pop ecx

loc_0_7F: ; CODE XREF: _mainCRTStartup+61j
and [ebp+var_4], 0
call __ioinit
call dword ptr ds:__imp__GetCommandLineA@0
mov dword ptr ds:__acmdln, eax
call ___crtGetEnvironmentStringsA
mov ds:__aenvptr, eax
call __setargv
call __setenvp
call __cinit
mov eax, dword ptr ds:__environ
mov dword ptr ds:___initenv, eax
push eax
push dword ptr ds:___argv
push dword ptr ds:___argc
call _main
add esp, 0Ch
mov [ebp+var_1C], eax
push eax
call _exit

$L17239: ; DATA XREF: .rdata:000000F8o
mov eax, [ebp+var_14]
mov ecx, [eax]
mov ecx, [ecx]
mov [ebp+var_20], ecx
push eax
push ecx
call __XcptFilter
pop ecx
pop ecx

$L17241:
retn
_mainCRTStartup endp ; sp = -34h

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

:00401683 55
:00401684 8BEC
:00401686 6AFF
:00401688 6810134000
:0040168D 6848214000
push ebp
mov ebp, esp
push FFFFFFFF
push 00401310
push 00402148
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040161B(C)
:00401692 64A100000000
:00401698 50
:00401699 64892500000000
:004016A0 83EC10
:004016A3 53
:004016A4 56
:004016A5 57
:004016A6 8965E8
:004016A9 FF1504104000
:004016AF 33D2
:004016B1 8AD4
:004016B3 8915743E4000
:004016B9 8BC8
:004016BB 81E1FF000000
:004016C1 890D703E4000
:004016C7 C1E108
:004016CA 03CA
:004016CC 890D6C3E4000
:004016D2 C1E810
:004016D5 A3683E4000
:004016DA 6A00
:004016DC E833090000
:004016E1 59
:004016E2 85C0
:004016E4 7508
:004016E6 6A1C
:004016E8 E89A000000
:004016ED 59
mov eax, dword ptr fs:[00000000]
push eax
mov dword ptr fs:[00000000], esp
sub esp, 00000010
push ebx
push esi
push edi
mov dword ptr [ebp-18], esp
call dword ptr [00401004]
xor edx, edx
mov dl, ah
mov dword ptr [00403E74], edx
mov ecx, eax
and ecx, 000000FF
mov dword ptr [00403E70], ecx
shl ecx, 08
add ecx, edx
mov dword ptr [00403E6C], ecx
shr eax, 10
mov dword ptr [00403E68], eax
push 00000000
call 00402014
pop ecx
test eax, eax
jne 004016EE
push 0000001C
call 00401787
pop ecx
И так далее и тому подобное...

Чуете чем пахнет??? Уже можно так составить строку для поиска:

558BEC6AFF68????????68????????64A1????????5064????????????83EC105356578965E8FF
15????????33D28AD4. По моему, хватит :)). При желании добавьте еще...

Я специально откомпилировал с разными версиями библиотек и посмотрел, что будет. Ну что я могу сказать... Переборщили мы малость, но код до FF15 везде одинаковый, дальше отличается, но самую малость. Так что финальная версия строки:

558BEC6AFF68????????68????????64A1????????5064????????????83EC105356578965E8

IV. Подводим итоги:

Мне действительно нечего сказать, поскольку OEP мы нашли. Также, хочу отметить, что распознать VC++ приложение оччень просто по строке "Microsoft Visual C++ runtime library" в сегменте данных. Далее, я взял UnPack 2.1, который может определять компиляторы по такой же видимо технологии. Он сказал, что мои .exe от "Microsoft Visual C++ 5.0 compiler". Значит, этот код там тоже не менялся. Единственная проблема: ранние и поздние версии. У меня их нет, кто може прислать сигнатуры - пишите, буду оччень благодарен.

Вот собственно и все! :)

Endnote:
© 2001 aSL! (asl@aslsoft.com )
This essay can be freely distributed/ published/ printed etc... as long as no modifications are made in any way.
Greets to: Everyone in UOFG www.uofg.com.ua


<= Вернуться к статьям

Rambler's Top100