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

Распаковка нового AsProtect-а

новое:
  • Отсутствие таблицы адресов импортируемых функций (IAT)
  • Улучшенный детектинг SoftIce
  • По-другому генерируются переходники
  • всяко что-то забыл... ;)
Используемые инструменты:
  • SoftIce из DriverStudio v4.2.7 + IceExt + SuperBPM
  • Hiew v6.85
  • Delphi 7
сразу хочу сказать, что сия статья не говорит "как надо делать". я хотел лишь поделиться, как распаковал прогу сам.

подопытную программу можно взять тут. версия АсПротекта или 1.3бета, или 1.23RC-какой-то-там.

по поводу детектинга SoftIce. в подробности вдаваться не было времени. однако, IceDump под W9x сайс уже не прячет. под NT прячет последний IceExt. а в любом случае BPX MapViewOfFile вообще ни к чему хорошему не приведет ;)

итак, начнем. OEP находится старинным методом - bpm esp-4. остановимся на "popad ; push eax ; ret ". сразу можно сдампить прогу.
как я обычно делаю, смотрю по полученному дампу что там творится..
смотрим на OEP

.0040168C:  jmps       .00040169E  ----- (1)
.0040168E:  bound       di,[edx]
.00401691:  inc         ebx
.00401692:  sub         ebp,[ebx]
.00401694:  dec         eax
.00401695:  dec         edi
.00401696:  dec         edi
.00401697:  dec         ebx
.00401698:  nop
.00401699:  jmp         00050B736
.0040169E:  mov         eax,[0050A08B]
.004016A3:  shl         eax,002 
.004016A6:  mov         [0050A08F],eax
.004016AB:  push        edx
.004016AC:  push        000
.004016AE:  call       .00050871E  ----- (2)
Поскольку программа наша написана на BCB, функция .50871E явно GetModuleHandleA. смотрим дальше.
.0050871E:  call        d,[00BBCFC4]
.00508724:  jmp         d,[00BBD0F8]
.0050872A:  jmp         d,[00BBD14C]
.00508730:  jmp         d,[00BBD468]
.00508736:  jmp         d,[00BBD474]
ого-го. вместо 00BBxxxx вообще-то должны быть адреса IAT-овской ячейки для конкретной функции. еще вместо JMP аспр понавставлял CALL.
глянув туда, где должна быть IAT (пятая по счету секция) -- там сплошной мусор, IAT-ом и не пахнет.
таким образом, делаем заключение, что IAT вообще не используется, а вызовы функций перенаправляются сразу на переходники. одним ImpRec-ом тут, естесственно, ничего сделать нельзя.
чтобы разобраться, где и как генерируются адреса переходников, ставим BPM 50871E+2. отловим уже при записи адреса переходника в [508720]. потрассировав, увидим, что для получения адреса функции вызывается GetProcAddress. только не он сам, а его переходник. затем вызывается функция, которая по оригинальному адресу функции возвращает адрес готового переходника.
хочется сказать, что отлавливать "оригинальные адреса функций" нужно не в одном месте, а в трех.
в первом случае адрес возвращается по имени функции, во втором по ординалу, в третьем еще как-то. у меня не было времени на поиск изысканных методов как вытащить адреса функций. я написал dll-ку с функциями для каждого из трех методов.
procedure P; cdecl;
var IATRVA, ProcAddr, DllBase: dword;
    t: text;
    p: pchar;
begin
  asm
    mov  IATRVA,   ebx    // адрес, куда будет помещен адрес переходника
    mov  ebx, [ebp+30h]   // имя функции
    mov  p, ebx           
    mov  ebx,  [ebp+2Ch]  // ModuleHandle библиотеки, из которой импортируется функция
    mov  DllBase,  ebx
  end;
  {$I-}
  AssignFile(t, 'import.txt');
  append(t);
  writeln(t, Format('%x %x %s',[IATRVA, ProcAddr, string(p)]));
  closefile(t);
end;
затем в теле аспровой функции получения адреса переходника пишем:
pushad
push        имя нашей длл
call        LoadLibraryA
push        имя нашей функции в длл
push        eax
call        GetProcAddress
call        eax  ; вызываем функцию
popad
jmp         GetProcAddress 
GetProcAddress после popad сделает все вместо аспровой функции. а до этого мы сделали все что нам надо.
таким образом в файле import.txt будет инфа о части функций. примерно то же самое нужно сделать и с двумя другими функциями получения адресов.
затем, я накидал прожку, которая составляет полностью весь IAT, поправляет в программе JMP/CALL [аспр] строго на JMP [IAT offset]. брякнувшись на OEP загрузил свой IAT по адресу 552000 и подсунул ImpRec-у.
не хватало 2-х функций: GetProcAddress и FindResourceA. ручками поправили. Fix Dump. фуф. вроде все.

ан нет. при запуске программы вылетает exception. после отладки выясняется, что аспр перекинул пару функций из программы в свое тело и запускал их от туда следующим методом:

.004D2268:  push        000B7CA44
.004D226D:  retn
..................................
.004D3110:  push        000B7CB2D
.004D3115:  retn
опять лезем в запакованный .ехе-шник и выцепляем функции, вставив ее куда-нибудь в область с кучей нулей. запускаем. ура. работает :-)
по-хорошему надо бы сваять утиль для получения импорта. но совершенно нет времени. дерзайте те, кому время позволяет.

на этом всё.

приветы летят к //PRA, //UOFG, VaG, Zwei и всем-всем-всем ;-)

(q) 26 oct 2003, deus [ deus@hotbox.ru ]

Rambler's Top100