脫Remote Administrator v2.0的殼 (8千字)
Remote Administrator v2.0
http://www.famatech.com/radmin20.zip : size 1,482,243 bytes
Radmin.exe : size 1,032,192 bytes
你是怎麼知道它是用Armadillo加的殼?fiv245報是VC6的,但是它的確是經過了處理,OEP是 ACEBFC。
加殼程式並不像其它的把被還原出來資料放到已預定下來的section裡,而是放在動態分配出來的空間,
所以pedump dump出來的exe也不過是加殼還原程式,這真的讓我們一下子束手無策!
bpmb ds:acebfc w,發現 1401422 的 CALL 1401BE0 就是還原始碼到OEP的。
再細看加殼還原程式就知道有六個 section 透過上面的call被還原了。
分別是:
RVA size alignment
1000 3822A 39000
3A000 4C7A 5000
3F000 1E13C 1F000
5E000 447C 5000
63000 400 1000
64000 11C18D 11D000
[0140FE30] 存放原image base : AA0000
往上看在 140137E 有 CALL 1401BE0,這裡是“還原”PIMAGE_NT_HEADERS32,好像什麼都有了,
將 AA0000 到 AA0000 + 64000 + 11D000 (section alignment是1000) dump出來不就行了嗎?
唔?沒有圖示?用Peditor看section table,才五個section,什麼都是空的,看directory的
resource又說出錯,慘了,初步斷定無藥可救!
再用eXeScope看原Radmin.exe,在resource裡看到有ICON, MENU, BITMAP等等,反正算是齊全了。
對,就是差這些了,把這些resource加到剛才dump出來的exe裡去!
directory裡的resource RVA : 11000, size : EB498,不就是整個.rsrc section嗎。
好,先把dump出來exe的entry point改為 2EBFC, image base改為 AA0000,directory 裡所有的RVA, size先全改為0
再將每個section的正確值修改回去,如上列出的
第一個section
name : (隨便)
Virtual Address : 1000
Virtual Size : 39000
Raw Offset : 1000
Raw Size : 39000
Characteristics : E00000E0
如此類推,最後加上我們的.rsrc,resource section. RVA 181000, size 11D000,改directory的
resource RVA 181000, size EC000。
用Hex workshop將Radmin.exe的.rsrc section(Offset 10000, size EC000) copy出來,
追加到dump出來exe的最後,存檔,咦?依然未見圖示??
再用Peditor看directory的resource的詳細列表,ICON, MENU, BITMAP等等都有了,選中cursor
下的21子項,在Item Info 組合框中的 RVA to Data 是 393A8,size : 134。
哦,原來RVA 393A8 並不是指向我們新加的.rsrc section。
最笨的方法就是把這些RVA to Data逐個修正過來,可是Peditor不可以修改該值,天啊,天曉得在.rsrc這堆“垃圾”裡改哪個值才是!
還是寫程式吧,幸好在找有關resource結構的時候找到有列舉resource的程式,修改一下就可以用了。
以下程式是裁剪並修改MSDN 的 Peering Inside the PE: A Tour of the Win32 Portable Executable
File Format裡的程式,
(那些printf 我都沒有去掉), fix_value 就是要修正的量。
new section RVA
old section RVA alignment diff
|
|
|
DWORD fix_value = 0x181000 -
0x10000 - 0x1000;
resDataEntry->OffsetToData = resData_RVA + fix_value;
先把.rsrc整個section save as 為res.bin, 程式是將res.bin map到記憶體,再修改OffsetToData,
記住執行一次該程式就可以了,再將該res.bin貼上回dump出來的exe去,exe圖示就會出現了。
最後是import table的重建了(唉,太累了!!!)。
在Import REConstructor的OEP裡填2EBFC,get import不成功,原因是OEP所對應的image base 是AA0000,
而不是01400000,在load radmin.exe, trw裡下 mod32. 顯示:
hMod PEHeader Base Module No
ModuleName
---- -------- -------- -------- -- ----------
xxxx 81991A58 01400000 xxxxxxxx xx RADMIN.EXE
d ds:81991A58 + 34 處就是image base 01400000,改其為 00AA0000
再在Import REConstructor 裡get import就成功了,只有一個1401000不知道, 暫定為GetModuleFileNameA。
(後來沒仔細看對不對了),至此脫殼完成。程式有自檢,這裡就不說了。
/* fixres.cpp */
/* cl fixres.cpp user32.lib */
#include <stdio.h>
#include <windows.h>
BOOL bFixIt = TRUE;
DWORD fix_value = 0x181000 - 0x10000 - 0x1000;
// Function prototype (necessary because two functions recurse)
void DumpResourceDirectory
(
PIMAGE_RESOURCE_DIRECTORY resDir, DWORD resourceBase,
DWORD level, DWORD resourceType
);
// The predefined resource types
char *SzResourceTypes[] = {
"???_0", "CURSOR", "BITMAP", "ICON", "MENU", "DIALOG", "STRING", "FONTDIR",
"FONT", "ACCELERATORS", "RCDATA", "MESSAGETABLE", "GROUP_CURSOR",
"???_13", "GROUP_ICON", "???_15", "VERSION"
};
// Get an ASCII string representing a resource type
void GetResourceTypeName(DWORD type, PSTR buffer, UINT cBytes)
{
if ( type <= 16 )
strncpy(buffer, SzResourceTypes[type],
cBytes);
else
wsprintf(buffer, "%X", type);
}
//
// If a resource entry has a string name (rather than an ID), go find
// the string and convert it from unicode to ascii.
//
void GetResourceNameFromId
(
DWORD id, DWORD resourceBase, PSTR buffer, UINT cBytes
)
{
PIMAGE_RESOURCE_DIR_STRING_U prdsu;
// If it's a regular ID, just format it.
if ( !(id & IMAGE_RESOURCE_NAME_IS_STRING) )
{
wsprintf(buffer, "%X", id);
return;
}
id &= 0x7FFFFFFF;
prdsu = (PIMAGE_RESOURCE_DIR_STRING_U)(resourceBase + id);
// prdsu->Length is the number of unicode characters
WideCharToMultiByte(CP_ACP, 0, prdsu->NameString, prdsu->Length,
buffer, cBytes, 0, 0);
buffer[ min(cBytes-1,prdsu->Length) ] = 0; //
Null terminate it!!!
}
//
// Dump the information about one resource directory entry. If the
// entry is for a subdirectory, call the directory dumping routine
// instead of printing information in this routine.
//
void DumpResourceEntry
(
PIMAGE_RESOURCE_DIRECTORY_ENTRY resDirEntry,
DWORD resourceBase,
DWORD level
)
{
UINT i;
PIMAGE_RESOURCE_DATA_ENTRY resDataEntry;
DWORD resData_RVA;
char nameBuffer[128];
if ( resDirEntry->OffsetToData & IMAGE_RESOURCE_DATA_IS_DIRECTORY
)
{
DumpResourceDirectory( (PIMAGE_RESOURCE_DIRECTORY)
((resDirEntry->OffsetToData
& 0x7FFFFFFF) + resourceBase),
resourceBase, level,
resDirEntry->Name);
return;
}
// Spit out the spacing for the level indentation
for ( i=0; i < level; i++ )
printf(" ");
if ( resDirEntry->Name & IMAGE_RESOURCE_NAME_IS_STRING
)
{
GetResourceNameFromId(resDirEntry->Name,
resourceBase, nameBuffer,
sizeof(nameBuffer));
printf("Name: %s Offset: %08X\n",
nameBuffer, resDirEntry->OffsetToData);
}
else
{
printf("ID: %08X Offset: %08X\n",
resDirEntry->Name,
resDirEntry->OffsetToData);
}
resDataEntry = (PIMAGE_RESOURCE_DATA_ENTRY)(resDirEntry->OffsetToData
+ resourceBase);
resData_RVA = resDataEntry->OffsetToData;
printf("Resource data RVA is : %08X\n", resData_RVA);
if ( bFixIt )
resDataEntry->OffsetToData = resData_RVA
+ fix_value;
}
//
// Dump the information about one resource directory.
//
void DumpResourceDirectory
(
PIMAGE_RESOURCE_DIRECTORY resDir,
DWORD resourceBase,
DWORD level,
DWORD resourceType
)
{
PIMAGE_RESOURCE_DIRECTORY_ENTRY resDirEntry;
char szType[64];
UINT i;
// Spit out the spacing for the level indentation
for ( i=0; i < level; i++ )
printf(" ");
// Level 1 resources are the resource types
if ( level == 1 && !(resourceType & IMAGE_RESOURCE_NAME_IS_STRING)
)
{
GetResourceTypeName( resourceType, szType,
sizeof(szType) );
}
else // Just print out the regular id or
name
{
GetResourceNameFromId( resourceType, resourceBase,
szType,
sizeof(szType) );
}
printf(
"ResDir (%s) Named:%02X ID:%02X TimeDate:%08X
Vers:%u.%02u Char:%X\n",
szType, resDir->NumberOfNamedEntries,
resDir->NumberOfIdEntries,
resDir->TimeDateStamp, resDir->MajorVersion,
resDir->MinorVersion,resDir->Characteristics);
resDirEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(resDir+1);
for ( i=0; i < resDir->NumberOfNamedEntries; i++, resDirEntry++
)
DumpResourceEntry(resDirEntry, resourceBase,
level+1);
for ( i=0; i < resDir->NumberOfIdEntries; i++, resDirEntry++
)
DumpResourceEntry(resDirEntry, resourceBase,
level+1);
}
//
// Top level routine called to dump out the entire resource hierarchy
//
void DumpResourceSection( LPVOID pmapbase )
{
IMAGE_RESOURCE_DIRECTORY *resDir;
resDir = (IMAGE_RESOURCE_DIRECTORY*) pmapbase;
printf("Resources\n");
DumpResourceDirectory(resDir, (DWORD)resDir, 0, 0);
}
int main( void )
{
HANDLE hfile, hMap;
LPVOID p_MapFile;
if ( (hfile = CreateFile("res.bin", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ
+ FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE
)
{
printf("Can not open file res.bin\n");
exit(1);
}
if ( (hMap = CreateFileMapping(hfile, NULL, PAGE_READWRITE, 0, 0, NULL))
== NULL )
{
CloseHandle( hfile );
printf("Can not create file mapping!\n");
exit(1);
}
if ( (p_MapFile = MapViewOfFile(hMap, FILE_MAP_WRITE, 0, 0, 0)) == NULL
)
{
CloseHandle( hfile );
CloseHandle( hMap );
printf("Can not map file!\n");
exit(1);
}
__try
{
DumpResourceSection( p_MapFile );
}
__except(1)
{
printf("Error when processing file!\n");
}
UnmapViewOfFile( p_MapFile );
CloseHandle( hfile );
CloseHandle( hMap );
return 0;
}
相關文章
- FTPrint的脫殼(asprotect) (2千字)2001-02-05FTP
- 脫殼----對用pecompact加殼的程式進行手動脫殼
(1千字)2000-07-30
- 脫Crunch/PE -> BitArts的殼。 (3千字)2002-05-03
- jdpack的脫殼及破解 (5千字)2002-06-25
- HTMLZip 1.0 beta 的脫殼 (3千字)2001-02-03HTML
- PicturesToExe3.51的脫殼 (2千字)2001-04-22REST
- 手工脫殼 Advanced Administrative Tools 4.0a (8千字)2000-06-06
- telock脫殼總結 (12千字)2001-09-27
- ASPROtect 1.22加殼的ahaview2.0脫殼 (5千字)2002-03-24View
- 脫Flashfxp 1.3 build 780的殼 (10千字)2001-08-15UI
- 脫PicturesToExe v3.60的殼 (1千字)2001-09-15REST
- 脫殼----對用Petite2.2加殼的程式進行手動脫殼的一點分析
(5千字)2000-07-27
- 用Armadillo標準加殼的程式的脫殼和引入表修復方案---OLLYDBG (8千字)2015-11-15
- 先分析,再脫殼(二) (13千字)2003-09-04
- WinKawaks 1.45脫殼筆記
(10千字)2002-08-12筆記
- 一點脫殼經驗。(7千字)2001-04-20
- The Bat! 1.39脫殼筆記 (1千字)2000-03-12BAT筆記
- 對PECompact加殼的DLL脫殼的一點分析 (7千字)2000-08-17
- 脫Advanced Email Extractor PRO的殼 (19千字)2001-08-19AI
- 殼的工作原理脫殼2013-04-10
- 股市風暴4.0的外殼分析與脫殼方法(一) (7千字)2001-06-10
- 手動脫殼的教程(由petite v2.2加殼) (4千字)2001-11-26
- ArtCursors 3.03 ASPR殼軟體脫殼後修整記 (10千字)2015-11-15
- 睡不著,帖一個:aspr程式的脫殼修復體會
(8千字)2015-11-15
- 對Asprotect脫殼的一點總結
(20千字)2000-08-12
- Asprotect 1.2x 加殼的 Advanced Direct
Remailer 2.17 脫殼 (3千字)2002-06-20REMAI
- Armadillo 2.52加殼原理分析和改進的脫殼方法
(12千字)2015-11-15
- 用OD對Aspr加殼程式的手動脫殼及修復 (7千字)2015-11-15
- aspr脫殼總結(部分適用於其他殼保護) (3千字)2001-09-14
- 手動脫掉Asprotect的殼,(給初學者的) (9千字)2002-01-24
- 不脫殼破解極光多能鬧鐘
(16千字)2003-04-14
- EZIP1.0脫殼手記 ――娃娃/[CCG] (3千字)2001-11-16
- Lock98主程式脫殼筆記 (1千字)2015-11-15筆記
- 壹次脫殼法――Armadillo 雙程式標準殼 快速脫殼2015-11-15
- VBExplorer.exe脫殼教程
附脫殼指令碼2015-11-15指令碼
- ASPRTECT1.2X加殼的Delphi
Application Peeper Pro 2.3.1.9 脫殼(簡單) (3千字)2002-04-06APP
- 談談如何使用加殼保護自己的軟體不被常用方法脫殼(2千字)2000-10-10
- 關於用ASProtect v1.3加殼軟體的脫殼方法體會 (5千字)2001-11-21