导入esp文件
esp文件 时间:2021-04-12 阅读:(
)
注入你的代码到可执行文件cntrump译由于本人的水平有限,存的错误在所难免,希望各位看官在阅读的过程中能将所发现的错误通过电子邮件的方式批评指正.
也欢迎大家能和我一起交流.
E-Mail:cntrump@gmail.
comQQ:136584897目录下载.
2内容.
30前言.
41必要条件42PE文件格式.
52.
1MS-DOS数据.
52.
2WindowsNT数据.
122.
3节头和节.
153调试器,反汇编器和一些有用工具173.
1调试器173.
1.
1SoftICE.
183.
1.
2OllyDbg.
193.
1.
3调试器界面哪部分才重要203.
2反汇编器.
223.
2.
1Proviewdisassembler223.
2.
2W32Dasm.
233.
2.
3IDAPro233.
3一些有用的工具.
233.
3.
1LordPE233.
3.
2PEiD.
243.
3.
3ResourceHacker.
243.
3.
4WinHex.
253.
3.
5CFFExplorer.
254添加新节并修改OEP.
264.
1恢复并重建PE文件294.
2为新节创建数据.
304.
3在创建新PE文件时的一些注意事项.
314.
4链接VC工程时的一些注意事项.
325存储导入表数据并到达原始OEP335.
1恢复首次寄存器的上下文.
355.
2恢复原始栈.
365.
3通过结构化异常处理到达OEP.
375.
3.
1实现异常处理.
405.
3.
2通过调整线程上下文到达OEP.
436构建导入表并重建原始导入表.
486.
1创建客户导入表.
506.
2运行时使用API函数.
546.
3修正原始导入表.
577支持DLL和OCX587.
1两次进入OEP597.
2实现重定位表.
617.
3构建特别的导入表668PreservetheThreadLocalStorage.
679注入你的代码.
6910结论.
69下载PEViewerPEMaker-Step1–添加新节.
PEMaker-Step2-TraveltowardsOEP.
PEMaker-Step3–支持导入表.
PEMaker-Step4–支持DLL和OCX.
PEMaker-Step5–完工.
CALC.
EXE–测试文件内容0.
前言1.
必要条件2.
PE文件格式o2.
1MS-DOS数据o2.
2WindowsNT数据o2.
3节头和节3.
调试器,反汇编器和一些有用工具o3.
1调试器3.
1.
1SoftICE3.
1.
2OllyDbg3.
1.
3在调试器界面中哪部分重要o3.
2反汇编器3.
2.
1Proviewdisassembler3.
2.
2W32Dasm3.
2.
3IDAProo3.
3一些有用工具3.
3.
1LordPE3.
3.
2PEiD3.
3.
3ResourceHacker3.
3.
4WinHex3.
3.
5CFFExplorer4.
添加新节并修改OEPo4.
1恢复并重建PE文件o4.
2为新节创建数据o4.
3创建新的PE文件要注意的事项o4.
4链接VC工程要注意的事项5.
存储重要数据并跳到原始OEPo5.
1存储首次寄存器的上下文o5.
2存储原始栈o5.
3根据构建的异常处理找到OEP5.
3.
1实现异常处理5.
3.
2依靠调整线程的上下文到达OEP6.
构建一个导入表并修复原始导入表o6.
1构建客户导入表o6.
2在运行时使用其它的API函数o6.
3修正原始导入表7.
支持DLL和OCXo7.
1两次进入OEPo7.
2实现重定位表o7.
3构建一个特殊的导入表8.
保护TLS9.
注入你的代码10.
结尾0前言Itmightbe,youdemandtocomprehendthewaysavirusprograminjectsitsprocedureintotheinteriorofaportableexecutablefileandcorruptsit,oryouareinterestedinimplementingapackeroraprotectorforyourspecificintentiontoencryptthedataofyourportableexecutable(PE)file.
ThisarticleiscommittedtorepresentabriefintuitiontorealizetheperformancewhichisaccomplishedbyEXEtoolsorsomekindofmal-wares.
可能,你需要理解病毒程序注射它的指令到一个PE文件内部并腐化它的方法,或者你只是感兴趣于实现一个壳或加密器为你的可执行文件对指定的数据进行加密.
这篇文章展现了一些EXE工具或者某些"坏东西"已经实现的原理的简单思路.
YoucanemploythesourcecodeofthisarticletocreateyourcustomEXEbuilder.
ItcouldbeusedtomakeanEXEprotectorintherightway,orwithawrongintention,topullulateavirus.
However,mypurposeofwritingthisarticlehasbeentogazeonthefirstapplication,soIwillnotberesponsiblefortheimmoralusageofthesemethods.
你可以用本文章的源码来创建你自己的EXEbuilder.
它可以用于制作EXE保护器,或者怀着错误的意图萌生出一个病毒.
无论如何,我写这篇文章之前,早已经有了第一个这样的程序,所以我不会为邪恶的用途负责.
1必要条件Therearenospecificmandatoryprerequisitestofollowthetopicsinthisarticle.
Ifyouarefamiliarwithdebuggerandalsotheportablefileformat,Isuggestyoutodropthesections2and3,thewholeofthesesectionshavebeenmadeforpeoplewhodonthaveanyknowledgeregardingtheEXEfileformatandalsodebuggers.
对于这篇文章的主题并没有明确要求的必要条件.
如果你对调试器和PE文件很熟悉,我建议你跳过第2和第3部分,这些章节是为了毫无PE文件格式和调试器知识的人准备的.
2PE文件格式ThePortableExecutablefileformatwasdefinedtoprovidethebestwayfortheWindowsOperatingSystemtoexecutecodeandalsotostoretheessentialdatawhichisneededtorunaprogram,forexampleconstantdata,variabledata,importlibrarylinks,andresourcedata.
ItconsistsofMS-DOSfileinformation,WindowsNTfileinformation,SectionHeaders,andSectionimages,Table1.
PE文件格式被定义用来提供一种最好的方法,在程序需要被执行时Windows操作系统执行代码和存储必要的数据.
例如常量,变量,导入库链接和资源数据.
它存在于MS-DOS文件格式,WindowsNT文件格式,节头,和节映像,表1.
2.
1MS-DOS数据ThesedataletyourememberthefirstdaysofdevelopingtheWindowsOperatingSystem,thedays.
WewereatthebeginningofawaytoachieveacompleteOperatingSystemlikeWindowsNT3.
51(Imean,Win3.
1,Win95,Win98werenotperfectOSs).
TheMS-DOSdatacausesthatyourexecutablefilecallsafunctioninsideMS-DOSandtheMS-DOSStubprogramletsitdisplay:"ThisprogramcannotberuninMS-DOSmode"or"ThisprogramcanberunonlyinWindowsmode",orsomethingslikethesecommentswhenyoutrytorunaWindowsEXEfileinsideMS-DOS6.
0,wherethereisnofootstepofWindows.
Thus,thisdataisreservedforthecodetoindicatethesecommentsintheMS-DOSoperatingsystem.
ThemostinterestingpartoftheMS-DOSdatais"MZ"!
Canyoubelieve,itreferstothenameof"MarkZbikowski",oneofthefirstMicrosoftprogrammers这些数据让你记住那些开发Windows操作系统最开始的日子.
我们站在实现一个完整的操作系统系统就像WindowsNT3.
51(我是说,Win3.
1,Win95,Win98都不是完美的操作系统)的方法的起点.
当你的可执行文件在MS-DOS下调用函数时MS-DOS数据将引发MS-DOS子程序并显示:"ThisprogramcannotberuninMS-DOSmode"或"ThisprogramcanberunonlyinWindowsmode",或者一些注释像当你尝试在MS-DOS6.
0下运行一个Windows可执行文件,而这个程序只能在Windows下运行.
因此,这些数据是为了在MS-DOS操作系统下显示这些注释而被保留的.
最有趣的MS-DOS数据部分是"MZ"!
你能相信它与一个名为"MarkZbikowski"的微软最早的程序员之一有关吗Tome,onlytheoffsetofthePEsignatureintheMS-DOSdataisimportant,soIcanuseittofindthepositionoftheWindowsNTdata.
IjustrecommendyoutotakealookatTable1,thenobservethestructureofIMAGE_DOS_HEADERintheheaderinthe\VC7\PlatformSDK\include\folderorthe\VC98\include\folder.
IdonotknowwhytheMicrosoftteamhasforgottentoprovidesomecommentaboutthisstructureintheMSDNlibrary!
对我而言,只有在MS-DOS数据中的PE标志的偏移才是重要的,从而我可以使用它来找到WindowsNT数据的位置.
我仅建议你看一下表1,然后观察在\VC7\PlatformSDK\include\folder或者在\VC98\include\folder中的头文件里的IMAGE_DOS_HEADER的结构.
我不知道为什么微软开发小组会忘记在MSDN库中提供一些关于这个结构的一些注释.
e_lfanewistheoffsetwhichreferstothepositionoftheWindowsNTdata.
IhaveprovidedaprogramtoobtaintheheaderinformationfromanEXEfileandtodisplayittoyou.
Tousetheprogram,justtry:e_lfanew是指向WindowsNT数据的偏移量.
我提供了一个程序用来从一个可执行文件中得到头信息并显示出来.
使用这个程序,只需要:PEViewerDownloadsourcefiles-132Kbtypedefstruct_IMAGE_DOS_HEADER{//DOS.
EXEheader"MZ"WORDe_magic;//MagicnumberWORDe_cblp;//BytesonlastpageoffileWORDe_cp;//PagesinfileWORDe_crlc;//RelocationsWORDe_cparhdr;//SizeofheaderinparagraphsWORDe_minalloc;//MinimumextraparagraphsneededWORDe_maxalloc;//MaximumextraparagraphsneededWORDe_ss;//Initial(relative)SSvalueWORDe_sp;//InitialSPvalueWORDe_csum;//ChecksumWORDe_ip;//InitialIPvalueWORDe_cs;//Initial(relative)CSvalueWORDe_lfarlc;//FileaddressofrelocationtableWORDe_ovno;//OverlaynumberWORDe_res[4];//ReservedwordsWORDe_oemid;//OEMidentifier(fore_oeminfo)WORDe_oeminfo;//OEMinformation;e_oemidspecificWORDe_res2[10];//ReservedwordsLONGe_lfanew;//Fileaddressofthenewexeheader}IMAGE_DOS_HEADER,*PIMAGE_DOS_HEADER;Thissampleisusefulforthewholeofthisarticle.
这个例程对于整篇文章都是有用的.
表1–PE文件结构MS-DOSinformationIMAGE_DOS_HEADERDOSEXESignatureCollapseCopyCode00000000ASCII"MZ"00000002DW009000000004DW000300000006DW000000000008DW00040000000ADW00000000000CDWFFFF0000000EDW000000000010DW00B800000012DW000000000014DW000000000016DW000000000018DW00400000001ADW0000DOS_PartPagDOS_PageCntDOS_ReloCntDOS_HdrSizeDOS_MinMemDOS_MaxMemDOS_ReloSSDOS_ExeSPDOS_ChkSumDOS_ExeIPPDOS_ReloCSDOS_TablOffDOS_OverlayReservedwords0000001CDB000000003BDB000000003CDD000000F0OffsettoPEsignatureMS-DOSStubProgramCollapseCopyCode00000040.
.
!
\L!
Thisprogramcanno00000060tberuninDOSmode.
WindowsNTinformationIMAGE_NT_HEADERSSignaturePEsignature(PE)CollapseCopyCode000000F0ASCII"PE"IMAGE_FILE_HEADERMachineCollapseCopyCode000000F4DW014C000000F6DW0003000000F8DD3B7D8410000000FCDD0000000000000100DD0000000000000104DW00E000000106DW010FNumberOfSectionsTimeDateStampPointerToSymbolTableNumberOfSymbolsSizeOfOptionalHeaderCharacteristicsIMAGE_OPTIONAL_HEADER32MagicNumberCollapseCopyCode00000108DW010B0000010ADB070000010BDB000000010CDD0001280000000110DD00009C0000000114DD0000000000000118DD000124750000011CDD0000100000000120DD0001400000000124DD0100000000000128DD000010000000012CDD0000020000000130DW000500000132DW000100000134DW000500000136DW000100000138DW00040000013ADW00000000013CDD0000000000000140DD0001F00000000144DD00000400MajorLinkerVersionMinorLinkerVersionSizeOfCodeSizeOfInitializedDataSizeOfUninitializedDataAddressOfEntryPointBaseOfCodeBaseOfDataImageBaseSectionAlignmentFileAlignmentMajorOSVersionMinorOSVersionMajorImageVersionMinorImageVersionMajorSubsystemVersionMinorSubsystemVersionReservedSizeOfImageSizeOfHeadersCheckSum00000148DD0001D7FC0000014CDW00020000014EDW800000000150DD0004000000000154DD0000100000000158DD001000000000015CDD0000100000000160DD0000000000000164DD00000010SubsystemDLLCharacteristicsSizeOfStackReserveSizeOfStackCommitSizeOfHeapReserveSizeOfHeapCommitLoaderFlagsNumberOfRvaAndSizesIMAGE_DATA_DIRECTORY[16]ExportTableImportTableResourceTableExceptionTableCertificateFileRelocationTableDebugDataArchitectureDataGlobalPtrTLSTableLoadConfigTableBoundImportTableImportAddressTableDelayImportDescriptorCOM+RuntimeHeaderReservedSectionsinformationIMAGE_SECTION_HEADER[0]Name[8]CollapseCopyCode000001E8ASCII".
text"000001F0DD000126B0000001F4DD00001000000001F8DD00012800000001FCDD0000040000000200DD0000000000000204DD0000000000000208DW00000000020ADW00000000020CDD60000020CODE|EXECUTE|READVirtualSizeVirtualAddressSizeOfRawDataPointerToRawDataPointerToRelocationsPointerToLineNumbersNumberOfRelocationsNumberOfLineNumbersCharacteristicsIMAGE_SECTION_HEADER[n]CollapseCopyCode00000210ASCII".
data";SECTION00000218DD0000101C;VirtualSize=0x101C0000021CDD00014000;VirtualAddress=0x1400000000220DD00000A00;SizeOfRawData=0xA0000000224DD00012C00;PointerToRawData=0x12C0000000228DD00000000;PointerToRelocations=0x00000022CDD00000000;PointerToLineNumbers=0x000000230DW0000;NumberOfRelocations=0x000000232DW0000;NumberOfLineNumbers=0x000000234DDC0000040;Characteristics=INITIALIZED_DATA|READ|WRITE00000238ASCII".
rsrc";SECTION00000240DD00008960;VirtualSize=0x896000000244DD00016000;VirtualAddress=0x1600000000248DD00008A00;SizeOfRawData=0x8A000000024CDD00013600;PointerToRawData=0x1360000000250DD00000000;PointerToRelocations=0x000000254DD00000000;PointerToLineNumbers=0x000000258DW0000;NumberOfRelocations=0x00000025ADW0000;NumberOfLineNumbers=0x00000025CDD40000040;Characteristics=INITIALIZED_DATA|READSECTION[0]CollapseCopyCode00000400EA22DD77D723DD77"w#w000004089A18DD7700000000w.
.
.
.
000004102E1EC777831DC777.
-ww00000418FF1EC77700000000-w.
.
.
.
00000420939FE777D805E877ww00000428FDA5E777ADA9E977ww00000430A336E7770338E7776w>8w0000043841E3E677608DE777Aw`w00000440E61BE6772B2AE777w+*w000004487A17E67779C8E677zwyw00000450141BE777C130E777w0wSECTION[n]CollapseCopyCode0001BF0063002E0063006800c.
.
.
c.
h.
0001BF086D000A0043006100m.
.
.
C.
a.
0001BF106C00630075006C00l.
c.
u.
l.
0001BF18610074006F007200a.
t.
o.
r.
0001BF2011004E006F007400.
N.
o.
t.
0001BF28200045006E006F00.
E.
n.
o.
0001BF307500670068002000u.
g.
h.
.
0001BF384D0065006D006F00M.
e.
m.
o.
0001BF407200790000000000r.
y.
.
.
.
.
0001BF480000000000000000.
.
.
.
.
.
.
.
0001BF500000000000000000.
.
.
.
.
.
.
.
0001BF580000000000000000.
.
.
.
.
.
.
.
0001BF600000000000000000.
.
.
.
.
.
.
.
0001BF680000000000000000.
.
.
.
.
.
.
.
0001BF700000000000000000.
.
.
.
.
.
.
.
0001BF780000000000000000.
.
.
.
.
.
.
.
2.
2WindowsNT数据Asmentionedintheprecedingsection,e_lfanewstorageintheMS-DOSdatastructurereferstothelocationoftheWindowsNTinformation.
Hence,ifyouassumethatthepMempointerrelatesthestartpointofthememoryspaceforaselectedportableexecutablefile,youcanretrievetheMS-DOSheaderandalsotheWindowsNTheadersbythefollowinglines,whichyoualsocanperceiveinthePEviewersample(pelib.
cpp,PEStructure::OpenFileName()):就像之前的部分说起的,在MS-DOS结构中e_lfanew保存着指向WindowsNT信息的位置.
因此,如果你把pMem指针与一个被选择的可执行文件在内存中的地址空间相关联起来,你就能检索MS-DOS头并用下面的代码找到WindowsNT头,就像你在PEview例程中看到的一样.
(pelib.
cpp,PEStructure::OpenFileName()):IMAGE_DOS_HEADERimage_dos_header;IMAGE_NT_HEADERSimage_nt_headers;PCHARpMem;memcpy(&image_dos_header,pMem,sizeof(IMAGE_DOS_HEADER));memcpy(&image_nt_headers,pMem+image_dos_header.
e_lfanew,sizeof(IMAGE_NT_HEADERS));Itseemstobeverysimple,theretrievaloftheheadersinformation.
IrecommendinspectingtheMSDNlibraryregardingtheIMAGE_NT_HEADERSstructuredefinition.
ItmakescomprehensibletograspwhattheimageNTheadermaintainstoexecuteacodeinsidetheWindowsNTOS.
Now,youareconversantwiththeWindowsNTstructure,itconsistsofthe"PE"Signature,theFileHeader,andtheOptionalHeader.
DonotforgettotakeaglimpseattheircommentsintheMSDNLibraryandbesidesinTable1.
检索头信息看起来非常简单,我建议阅读MSDN库中关于IMAGE_NT_HEADERS结构的定义.
掌握了WindowsNT的文件头结构后就容易理解一个可执行文件在Windows内部运行机理了.
现在,你熟悉了WindowsNT结构,它由"PE"标志,文件头,和可选头组成.
同时别忘了看一下在MSDN中关于它们的信息和表1.
Onethewhole,Iconsidermerely,onthemostcircumstances,thefollowingcellsoftheIMAGE_NT_HEADERSstructure:作为一个整体,我仅认为在大多数情况下,下列IMAGE_NT_HEADERS结构体的成员:FileHeader->NumberOfSectionsOptionalHeader->AddressOfEntryPointOptionalHeader->ImageBaseOptionalHeader->SectionAlignmentOptionalHeader->FileAlignmentOptionalHeader->SizeOfImageOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]->VirtualAddressOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]->SizeYoucanobserveclearly,themainpurposeofthesevalues,andtheirrolewhentheinternalvirtualmemoryspaceallocatedforanEXEfilebytheWindowsOSisfullyallocated,ifyoupayattentiontotheirexplanationsinMSDNlibrary,soIamnotgoingtorepeattheMSDNannotationshere.
你可以清楚地看到,这些主要的值,和当Windows操作系统为一个EXE文件完全申请所需的虚拟内存空间时它们扮演的角色,如果你专心看了MSDN中对它们的解释,那么我不打算在这里再反复说明MSDN了.
IshouldmentionabriefcommentregardingthePEdatadirectories,orOptionalHeader->DataDirectory[],asIthinkthereareafewaspectsofinterestconcerningthem.
WhenyoucometosurveytheOptionalheaderthroughtheWindowsNTinformation,youwillfindthatthereare16directoriesattheendoftheOptionalHeader,whereyoucanfindtheconsecutivedirectories,includingtheirRelativeVirtualAddressandSize.
Ijustmentionhere,thenotesfromtoclarifytheseinformation:我应该提到一个简短的解释关于PE数据目录,即OptionalHeader->DataDirectory[],作为我认为一些关于它们有趣的方面.
当你通过WindowsNT信息仔细观察可选头时,你会发现有16个目录在可选头的结尾,从那你可以发现连续的目录,包括它们相对的虚拟地址和大小.
我仅说到这里,从可以得到更多的信息.
#defineIMAGE_DIRECTORY_ENTRY_EXPORT0//ExportDirectory#defineIMAGE_DIRECTORY_ENTRY_IMPORT1//ImportDirectory#defineIMAGE_DIRECTORY_ENTRY_RESOURCE2//ResourceDirectory#defineIMAGE_DIRECTORY_ENTRY_EXCEPTION3//ExceptionDirectory#defineIMAGE_DIRECTORY_ENTRY_SECURITY4//SecurityDirectory#defineIMAGE_DIRECTORY_ENTRY_BASERELOC5//BaseRelocationTable#defineIMAGE_DIRECTORY_ENTRY_DEBUG6//DebugDirectory#defineIMAGE_DIRECTORY_ENTRY_ARCHITECTURE7//ArchitectureSpecificData#defineIMAGE_DIRECTORY_ENTRY_GLOBALPTR8//RVAofGP#defineIMAGE_DIRECTORY_ENTRY_TLS9//TLSDirectory#defineIMAGE_DIRECTORY_ENTRY_LOAD_CONFIG10//LoadConfigurationDirectory#defineIMAGE_DIRECTORY_ENTRY_BOUND_IMPORT11//BoundImportDirectoryinheaders#defineIMAGE_DIRECTORY_ENTRY_IAT12//ImportAddressTable#defineIMAGE_DIRECTORY_ENTRY_DELAY_IMPORT13//DelayLoadImportDescriptors#defineIMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR14//COMRuntimedescriptorThelastone(15)wasreservedforuseinfuture;IhavenotyetseenanypurposetouseiteveninPE64.
最后一个(第15个)被保留为未来所用;我从来没有看到它被使用过,甚至是在64位PE中.
Forinstance,ifyoudesiretoperceivetherelativevirtualaddress(RVA)andthesizeoftheresourcedata,itisenoughtoretrievethemby:引以为例,如果你想要了解相对虚拟地址(RVA)和资源数据的大小,这样检索就可以了:CollapseCopyCodeDWORDdwRVA=image_nt_headers.
OptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE]->VirtualAddress;DWORDdwSize=image_nt_headers.
OptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE]->Size;Tocomprehendmoreregardingthesignificanceofdatadirectories,Iforwardyoutosection3.
4.
3,MicrosoftPortableExecutableandtheCommonObjectFileFormatSpecificationdocumentbyMicrosoft,andfurthermoresection6ofthisdocument,whereyoudiscernthevarioustypesofsectionsandtheirapplications.
Wewilldiscussthesection'sadvantagesubsequently.
为了了解更多关于数据目录的重要性,我建议你跳到3.
43节,微软的MicrosoftPortableExecutableandtheCommonObjectFileFormatSpecification文档和此文档的第6节,你可以看到不同类型的节和它们的用处.
我们将在后面讨论这些节的特点.
2.
3节头和节WecurrentlyobservehowtheportableexecutablefilesdeclarethelocationandthesizeofasectiononadiskstoragefileandinsidethevirtualmemoryspaceallocatedfortheprogramwithIMAGE_NT_HEADERS->OptionalHeader->SizeOfImagebytheWindowstaskmanager,aswellthecharacteristicstodemonstratethetypeofthesection.
TounderstandbettertheSectionheaderasmypreviousdeclaration,IsuggesthavingashortgapeontheIMAGE_SECTION_HEADERstructuredefinitionintheMSDNlibrary.
ForanEXEpackerdeveloper,VirtualSize,VirtualAddress,SizeOfRawData,PointerToRawData,andCharacteristicscellshavesignificantrules.
WhiledevelopinganEXEpacker,youshouldbecleverenoughtoplaywiththem.
Therearesomethingstobenotedwhileyoumodifythem;youshouldtakecaretoaligntheVirtualSizeandVirtualAddressaccordingtoOptionalHeader->SectionAlignment,aswellasSizeOfRawDataandPointerToRawDatainlinewithOptionalHeader->FileAlignment.
Otherwise,youwillcorruptyourtargetEXEfileanditwillneverrun.
RegardingCharacteristics,IpayattentionmostlytoestablishasectionbyIMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE|IMAGE_SCN_CNT_INITIALIZED_DATA,Iprefermynewsectionhasabilitytoinitializesuchdataduringrunningprocess;suchasimporttable;besides,Ineedittobeabletomodifyitselfbytheloaderwithmysettingsinthesectioncharacteristicstoread-andwriteable.
我们现在观察PE文件怎样表示一个节在一个磁盘存储文件上的位置和大小和通过Windows任务管理器为程序用IMAGE_NT_HEADERS->OptionalHeader->SizeOfImage来申请虚拟内存空间,就像节的类型所说明的特点那样.
了为更好地理解我之前描述的节头,我建议快速浏览在MSDN库中的IMAGE_SECTION_HEADER结构体的定义.
作为一个EXE压缩器开发者,VirtualSize,VirtualAddress,SizeOfRawData,PointerToRawData,和Characteristics成员有重要的规则.
当开发一个EXE压缩器时,你应该足够精明地玩转它们.
在你修改它们的时候有一些东西需要注意;你应该根据OptionalHeader->SectionAlignment小心对齐VirtualSize和VirtualAddress,就像根据OptionalHeader->FileAlignment来排列SizeOfRawData和PointerToRawData一样.
否则你将弄坏你的目标文件而且它永远也运行不了.
关于Characteristics,我大部分使用IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE|IMAGE_SCN_CNT_INITIALIZED_DATA,来建立一个节.
我愿意我的程序在进程运行期间有能力初始化这些数据;例如导入表,而且我需要它根据我在节中设置的可读可写属性能被Loader修改自身.
Moreover,youshouldpayattentiontothesectionnames,youcanknowthepurposeofeachsectionbyitsname.
Iwilljustforwardyoutosection6:MicrosoftPortableExecutableandtheCommonObjectFileFormatSpecificationdocuments.
Ibelieve,itrepresentsthetotalityofsectionsbytheirnames,Table2.
此外,你应该关注节名,能过它们的名字你能知道每个节的作用.
我将只促进你到第6节:MicrosoftPortableExecutableandtheCommonObjectFileFormatSpecification文档.
我相信,通过它们的名字表明了全部的节,表2.
表2–节名".
text"CodeSection"CODE"CodeSectionoffilelinkedbyBorlandDelphiorBorlandPascal".
data"DataSection"DATA"DataSectionoffilelinkedbyBorlandDelphiorBorlandPascal".
rdata"SectionforConstantData".
idata"ImportTable".
edata"ExportTable".
tls"TLSTable".
reloc"RelocationInformation".
rsrc"ResourceInformationTocomprehendthesectionheadersandalsothesections,youcanrunthesamplePEviewer.
BythisPEviewer,youonlycanrealizetheapplicationofthesectionheadersinafileimage,sotoobservethemainsignificanceintheVirtualMemory,youshouldtrytoloadaPEfilebyadebugger,andthenextsectionrepresentsthemainideaofusingthevirtualaddressandsizeinthevirtualmemorybyusingadebugger.
ThelastnoteisaboutIMAGE_NT_HEADERS->FileHeader->NumberOfSections,thatprovidesanumberofsectionsinaPEfile,donotforgettoadjustitwheneveryouremoveoraddsomesectionstoaPEfile,Iamtalkingaboutsectioninjection!
为理解节头和节,你可以运行例程PEviewer.
通过PEviewer,你仅能认识到节头在一个文件映像中的应用,所以为了观察虚拟内存中的主要重要性,你应该尝试用调试器载入一个PE文件,在下一节中通过调试器在虚拟内存中使用虚拟地址和大小将作为主要内容.
最后要注意的是关于IMAGE_NT_HEADERS->FileHeader->NumberOfSections,提供了一个PE文件中节的数量,无论何时你移到或者添加一些节到一个PE文件别忘了调整它,我正在谈论的是关于节注入!
3调试器,反汇编器和一些有用工具Inthispart,youwillbecomefamiliarwiththenecessaryandessentialequipmentstodevelopyourPEtools.
在这部分,带着必需的和必要的装备来开发你的PE工具将成为常见的.
3.
1调试器Thefirstessentialprerequisite,tobecomeaPEtoolsdeveloper,istohaveenoughexperiencewithbugtracertools.
Furthermore,youshouldknowmostoftheassemblyinstructions.
Tome,theInteldocumentsarethebestreferences.
YoucanobtainthemfromtheIntelsiteforIA-32,andontopofthatIA-64;thefuturebelongstoIA-64CPUs,WindowsXP64-bit,andalsoPE64!
第一重要的必备条件,成为一个PE工具开发者,是有足够的经验使用bug追踪工具.
此外,你应该知道更多的反汇编用法.
对于我,Intel文档是最好的参考.
你可以从Intel站点得到它们的IA-32版本在IA-64版本之上;未来属于IA-64CPU,WindowsXP64位版,和64位PE文件!
IA-32IntelArchitectureSoftwareDevelopersManuals.
IntelItaniumArchitectureAssemblyLanguageReferenceGuide.
TheIntelItaniumProcessorDeveloperResourceGuide.
TotraceaPEfile,SoftICEbyCompuwareCorporation,IknewitalsoasnamedNuMegawhenIwasathighschool,isthebestdebuggerintheworld.
ItimplementsprocesstracingbyusingkernelmodemethoddebuggingwithoutapplyingWindowsdebuggingapplicationprogramminginterface(API)functions.
Inaddition,Iamgoingtointroduceoneperfectdebuggerinusermodelevel.
ItutilizestheWindowsdebuggingAPItotraceaPEfileandalsoattachesitselftoanactiveprocess.
TheseAPIfunctionshavebeenprovidedbyMicrosoftteams,insidetheWindowsKernel32library,totraceaspecificprocess,byusingMicrosofttools,orperhaps,tomakeyourowndebugger!
SomeofthoseAPIfunctionsinlude:CreateThread(),CreateProcess(),OpenProcess(),DebugActiveProcess(),GetThreadContext(),SetThreadContext(),ContinueDebugEvent(),DebugBreak(),ReadProcessMemory(),WriteProcessMemory(),SuspendThread(),andResumeThread().
为了追踪一个PE文件,CompuwareCorporation公司的SoftICE,当我在高中的时候,它名为NuMega,是世界上最好的调试器.
它不使用Windwos调试API实现了内核模式方法追踪进程.
另外,我准备介绍一个用户模式下的完美调试器.
它利用Windows调试API来跟踪PE文件并可以附加到一个活动的进程.
这些API函数由微软小组提供,在WindowsKernel32库内部,跟踪一个指定的进程,通过使用微软工具,或许,写一个你自己的调试器!
一些这样的API函数包括:CreateThread(),CreateProcess(),OpenProcess(),DebugActiveProcess(),GetThreadContext(),SetThreadContext(),ContinueDebugEvent(),DebugBreak(),ReadProcessMemory(),WriteProcessMemory(),SuspendThread(),和ResumeThread().
3.
1.
1SoftICEItwasin1987;FrankGrossmanandJimMoskundecidedtoestablishacompanycalledNuMegaTechnologiesinNashua,NH,inordertodevelopsomeequipmentstotraceandtestthereliabilityofMicrosoftWindowssoftwareprograms.
Now,itisapartofCompuwareCorporationanditsproducthasparticipatedtoacceleratethereliabilityinWindowssoftware,andadditionallyinWindowsdriverdevelopments.
Currently,everyoneknowstheCompuwareDriverStudiowhichisusedtoestablishanenvironmentforimplementingtheelaborationofakerneldriverorasystemfilebyaidingtheWindowsDriverDevelopmentKit(DDK).
ItbypassestheinvolvementofDDKtoimplementaportableexecutablefileofkernellevelforaWindowssystemsoftwaredeveloper.
Forus,onlyoneinstrumentofDriverStudioisimportant,SoftICE,thisdebuggercanbeusedtotraceeveryportableexecutablefile,aPEfileforusermodeleveloraPEfileforkernelmodelevel.
在1987年;FrankGrossman和JimMoskun决定在Nashua成立一个名为NuMegaTechnologiesr的公司.
NH,为了开发一些装备来追踪和测试微软Windows软件程序的可靠性.
现在它是CompuwareCorporation公司的一部分而且它的产品促进了Windows软件的可靠性,包括Windows驱动开发.
现在每个人都知道CompuwareDriverStudio,一个用来帮助DDK搭建开发内核驱动或者系统文件开发环境的工具.
它省去了DDK为Windows系统软件开发环境开发内核级可执行文件的繁琐配置.
对于我们,只有DriverStudio的一个工具才是重要的,SoftICE,可跟踪任何可执行文件,包括用户模式和内核模式.
图1-SoftICE窗口EAX=00000000EBX=7FFDD000ECX=0007FFB0EDX=7C90EB94ESI=FFFFFFFFEDI=7C919738EBP=0007FFF0ESP=0007FFC4EIP=010119E0odiszapcCS=0008DS=0023SS=0010ES=0023FS=0030GS=0000SS:0007FFC4=87C816D4F0023:010130000000000000000000-00000000000000000023:010130100100000020000000-0A0000000A0000000023:010130202000000000000000-53636943616C6300.
.
.
.
.
.
.
.
SciCalc.
0023:010130300000000000000000-6261636B67726F75.
.
.
.
.
.
.
.
backgrou0023:010130406E64000000000000-2E00000000000000nd.
0010:0007FFC44F6D817C3807917C-FFFFFFFF0090FD7FOm|8|.
0010:0007FFD4EDA65480C8FF0700-E8B4F581FFFFFFFFT.
0010:0007FFE4F399837C586D817C-0000000000000000Xm0010:0007FFF400000000E0190101-0000000000000000010119E0PUSHEBP010119E1MOVEBP,ESP010119E3PUSH-1010119E5PUSH01001570010119EAPUSH01011D60010119EFMOVEAX,DWORDPTRFS:[0]010119F5PUSHEAX010119F6MOVDWORDPTRFS:[0],ESP010119FDADDESP,-6801011A00PUSHEBX01011A01PUSHESI01011A02PUSHEDI01011A03MOVDWORDPTRSS:[EBP-18],ESP01011A06MOVDWORDPTRSS:[EBP-4],0:_3.
1.
2OllyDbgItwasabout4yearsago,thatIfirstsawthisdebuggerbychance.
Forme,itwasthebestchoice,IwasnotsowealthytopurchaseSoftICE,andatthattime,SoftICEonlyhadgoodfunctionsforDOS,Windows98,andWindows2000.
IfoundthatthisdebuggersupportedallkindsofWindowsversions.
Therefore,Istartedtolearnitveryfast,andnowitismyfavoritedebuggerfortheWindowsOS.
ItisadebuggerthatcanbeusedtotraceallkindsofportableexecutablefilesexceptaCommonLanguageInfrastructure(CLI)fileformatinusermodelevel,byusingtheWindowsdebuggingAPI.
OlehYuschuk,theauthor,isoneofworthiestsoftwaredevelopersIhaveseeninmylife.
HeisaUkrainianwhonowlivesinGermany.
Ishouldmentionherethathisdebuggeristhebestchoiceforhackerandcrackerpartiesaroundtheworld!
Itisafreeware!
YoucantryitfromOllyDbgHomepage.
大约4年前,我偶然的看见这个调试器.
对于我,它是最好的选择,我没有富余的钱购买SoftICE,而且在这个时候SoftICE只对DOS,Windows98,和Windows2000有很好的支持.
我发现这个调试器(OllyDbg)能支持全部Windows版本.
因此,我快速地开始学习它,现在它是我最喜爱的Windows系统调试器.
它是一个使用Windows调试API来支持所有可执行文件的调试器,除了CLI文件格式.
OlehYuschuk,作者,是一个在我一生中见过的最可敬的软件开发者.
他是一个现在生活在德国的乌克兰人.
我应该提到他的调试器是全世界黑客和破解组织最好的选择!
它是免费的!
你可以尝试它从OllyDbg的主页.
图2-OllyDbgCPU窗口3.
1.
3调试器界面哪部分才重要Ihaveintroducedtwodebuggerswithouttalkingabouthowyoucanemploythem,andalsowhichpartsyoushouldpayattentionmore.
Regardingusingdebuggers,Ireferyoutotheirinstructionsinhelpdocuments.
However,Iwanttoexplainshortlytheimportantpartsofadebugger;ofcourse,Iamtalkingaboutlow-leveldebuggers,orinotherwords,machine-languagedebuggersofthex86CPUfamilies.
我介绍了两个调试器除了它们的用法,和哪部分是你应该关注的.
关于使用调试器,我建议你参考它们的帮助文档.
无论如何,我想马上解释调试器和重要部分;当然我现在要讲关于低级调试器,换言之,x86CPU家族的机器语言调试器.
Alloflow-leveldebuggersconsistofthefollowingsubdivisions:所有低级调试器都包含下面这些部分:1.
Registersviewer.
寄存器查看EAXECXEDXEBXESPEBPESIEDIEIPodtszapc2.
DisassemblerorCodeviewer.
反汇编或代码窗口查看CollapseCopyCode010119E0PUSHEBP010119E1MOVEBP,ESP010119E3PUSH-1010119E5PUSH01001570010119EAPUSH01011D60010119EFMOVEAX,DWORDPTRFS:[0]010119F5PUSHEAX010119F6MOVDWORDPTRFS:[0],ESP010119FDADDESP,-6801011A00PUSHEBX01011A01PUSHESI01011A02PUSHEDI01011A03MOVDWORDPTRSS:[EBP-18],ESP01011A06MOVDWORDPTRSS:[EBP-4],03.
Memorywatcher.
内存查看0023:010130000000000000000000-00000000000000000023:010130100100000020000000-0A0000000A0000000023:010130202000000000000000-53636943616C6300.
.
.
.
.
.
.
.
SciCalc.
0023:010130300000000000000000-6261636B67726F75.
.
.
.
.
.
.
.
backgrou0023:010130406E64000000000000-2E00000000000000nd.
4.
Stackviewer.
栈查看0010:0007FFC44F6D817C3807917C-FFFFFFFF0090FD7FOm|8|.
0010:0007FFD4EDA65480C8FF0700-E8B4F581FFFFFFFFT.
0010:0007FFE4F399837C586D817C-0000000000000000Xm0010:0007FFF400000000E0190101-00000000000000005.
Commandline,commandbuttons,orshortcutkeystofollowthedebuggingprocess.
调试进程所用的命令行,命令按钮,或快捷键CommandSoftICEOllyDbgRunF5F9StepIntoF11F7StepOverF10F8SetBreakPointF8F2YoucancompareFigure1andFigure2todistinguishthedifferencebetweenSoftICEandOllyDbg.
WhenyouwanttotraceaPEfile,youshouldmostlyconsiderthesefivesubdivisions.
Furthermore,everydebuggercomprisesofsomeotherusefulparts;youshoulddiscoverthembyyourself.
你可以比较图1和图2区别SoftICE和OllyDbg之间的区别.
当你要跟踪一个PE文件,你应该快速考虑这5部分.
此外,每个调试器包含其它有用的部分;你应该自己发现它们.
3.
2反汇编器WecanconsiderOllyDbgandSoftICEasexcellentdisassemblers,butIalsowanttointroduceanotherdisassemblertoolwhichisfamousinthereverseengineeringworld.
我们知道OllyDbg和SoftICE是优秀的反汇编器,但是我也要介绍另一个反汇编工具它在逆向工程世界里是非常有名的.
3.
2.
1ProviewdisassemblerProvieworPVDasmisanadmirabledisassemblerbytheReverse-Engineering-Community;itisstillunderdevelopmentandbugfixing.
Youcanfinditsdisassmblersourceengineandemployittocreateyourowndisassembler.
Proview或PVDasm是一个由Reverse-Engineering-Community制作的绝妙的反汇编器;它现在仍然在开发和bug修复.
你可以找到它的反汇编引擎源码并在你自己的反汇编器里使用.
3.
2.
2W32DasmW32DASMcandisassembleboth16and32bitexecutablefileformats.
Inadditiontoitsdisassemblingability,youcanemployittoanalyzeimport,exportandresourcedatadirectoriesdata.
W32DASM可以反汇编16位和32位可执行文件格式.
另外它的反汇编能力,你可以用来分析导入,导出和资源数据目录数据.
3.
2.
3IDAProAllreverse-engineeringexpertsknowthatIDAProcanbeusedtoinvestigate,notonlyx86instructions,butthatofvariouskindsofCPUtypeslikeAVR,PIC,andetc.
Itcanillustratetheassemblysourceofaportableexecutablefilebyusingcoloredgraphicsandtables,andisveryusefulforanynewbieinthisarea.
Furthermore,ithasthecapabilitytotraceanexecutablefileinsidetheusermodelevelinthesamewayasOllyDbg.
所有的逆向工程专家都知道IDAPro能被用于研究,不仅x86指令,而且不同种类的CPU类型,像AVR,PIC等等.
它能通过有色的图形和表图示一个可执行文件的汇编源码,而且对于进入这个领域的新手非常有用.
此外,它能和OllyDbg一样对一个可执行文件进行用户级跟踪.
3.
3一些有用的工具AgoodPEtoolsdeveloperisconversantwiththetoolswhichsavehistime,soIrecommendtoselectsomeappropriateinstrumentstoinvestigatethebaseinformationunderaportableexecutablefile.
一个好的PE工具开发者熟知哪些工具可以节省时间,所以我建议选择适当的工具来研究在可执行文件下的基本信息.
3.
3.
1LordPELordPEbyy0daisstillthefirstchoicetoretrievePEfileinformationwiththepossibilitytomodifythem.
y0da写的LordPE仍然是首选的PE文件查看工具和修改工具.
3.
3.
2PEiDPEiDentifierisvaluabletoidentifythetypeofcompilers,packers,andcryptorsofPEfiles.
Asofnow,itcandetectmorethan500differentsignaturetypesofPEfiles.
PEiDentifier是用来侦测PE文件的编译器,壳和加密器的类型很有价值.
到目前为止,它可以侦测超过500种不同标志类型的PE文件.
3.
3.
3ResourceHackerResourceHackercanbeemployedtomodifyresourcedirectoryinformation;icon,menu,versioninfo,stringtable,andetc.
ResourceHacker被用于修改资源目录信息;图标,菜单,版本信息,字符串表等等.
3.
3.
4WinHexWinHex,itisclearwhatyoucandowiththistool.
WinHex,很清楚,你知道能用这个工具做什么.
3.
3.
5CFFExplorerEventually,CFFExplorerbyNtoskrnliswhatyouwishtohaveasaPEUtilitytoolinyourdream;itsupportsPE32/64,PErebuildincludedCommonLanguageInfrastructure(CLI)file,inotherwords,the.
NETfile,aresourcemodifier,andmuchmorefacilitieswhichcannotbefoundinothers,justtryanddiscovereveryunimaginableoptionbyhand.
最后,Ntoskrnl的CFFExplorer是一个你梦寐以求的PE实用工具;它支持32位/64位PE,PE重建包括CLI文件,换言之,.
NET文件,一个资源修改器,和很多在其他工具中找不到的功能,只要动手去尝试和探索每个不可思议的选项.
4添加新节并修改OEPWearereadytodothefirststepofmakingourproject.
SoIhaveprovidedalibrarytoaddanewsectionandrebuildtheportableexecutablefile.
Beforestarting,IlikeyougetfamiliarwiththeheadersofaPEfile,byusingOllyDbg.
YoushouldfirstopenaPEfile,thatpopsupamenu,View->Executablefile,againgetapopupmenuSpecial->PEheader.
AndyouwillobserveascenesimilartoFigure3.
Now,cometoMainMenuView->Memory,trytodistinguishthesectionsinsidetheMemorymapwindow.
我们已经准备好了创建我们工程的第一步.
所以我提供一个库来添加新节和重建PE文件.
在开始之前,我希望你已经通过使用OllyDbg熟悉了PE文件头.
你应该先打开一个PE文件,右键CPU窗口会弹出一个菜单,查看->可执行文件,再弹出另一个菜单指定->PE文件头.
你将会观察到类似于图3的的内容.
现在,来到主菜单查看->内存,尝试在内存窗口中识别节.
图3CollapseCopyCode00000000000000020000000400000006000000080000000A0000000C0000000E00000010000000120000001400000016000000180000001A0000001C0000001D0000001E0000001F0000002000000021000000220000002300000024CollapseCopyCode4D5A90000300000004000000FFFF0000B80000000000000040000000000000000000000000CollapseCopyCodeASCII"MZ"DW0090DW0003DW0000DW0004DW0000DWFFFFDW0000DW00B8DW0000DW0000DW0000DW0040DW0000DB00DB00DB00DB00DB00DB00DB00DB00DB00CollapseCopyCodeDOSEXESignatureDOS_PartPag=90(144.
)DOS_PageCnt=3DOS_ReloCnt=0DOS_HdrSize=4DOS_MinMem=0DOS_MaxMem=FFFF(65535.
)DOS_ReloSS=0DOS_ExeSP=B8DOS_ChkSum=0DOS_ExeIP=0DOS_ReloCS=0DOS_TablOff=40DOS_Overlay=000000025000000260000002700000028000000290000002A0000002B0000002C0000002D0000002E0000002F000000300000003100000032000000330000003400000035000000360000003700000038000000390000003A0000003B0000003C0000000000000000000000000000000000000000000000F0000000DB00DB00DB00DB00DB00DB00DB00DB00DB00DB00DB00DB00DB00DB00DB00DB00DB00DB00DB00DB00DB00DB00DB00DD000000F0OffsettoPEsignatureIwanttoexplainhowwecanplainlychangetheOffsetofEntryPoint(OEP)inoursamplefile,CALC.
EXEofWindowsXP.
First,byusingaPETool,andalsousingourPEViewer,wefindOEP,0x00012475,andImageBase,0x01000000.
ThisvalueofOEPistheRelativeVirtualAddress,sotheImageBasevalueisusedtoconvertittotheVirtualAddress.
我要解释在我们的样品文件中怎样明了的改变入口点的偏移(OEP),WindowsXP的CALC.
EXE.
首先,使用一个PE工具,也就是使用我们的PEViewer,找OEP,0x00012475和映像基址,0x01000000.
这个OEP的值是相对虚拟地址,这样映像基址的值被用于转换到虚拟地址.
Virtual_Address=Image_Base+Relative_Virtual_AddressCollapseCopyCodeDWORDOEP_RVA=image_nt_headers->OptionalHeader.
AddressOfEntryPoint;//OEP_RVA=0x00012475DWORDOEP_VA=image_nt_headers->OptionalHeader.
ImageBase+OEP_RVA;//OEP_VA=0x01000000+0x00012475=0x01012475PEMaker–第1步Downloadsourcefiles-54.
7KbCALC.
EXE–测试文件DownloadtestPEfile-49.
5KbDynLoader(),inloader.
cpp,isreservedforthedataofthenewsection,inotherwords,theLoader.
DynLoader(),在loader.
cpp中,被保留用于新节的数据,换言之,就是Loader.
DynLoader第1步CollapseCopyCode__stdcallvoidDynLoader(){_asm{DWORD_TYPE(DYN_LOADER_START_MAGIC)MOVEAX,01012475h//VirtualAddress=PEAlign(image_section_header[i]->VirtualAddress,image_nt_headers->OptionalHeader.
SectionAlignment);image_section_header[i]->Misc.
VirtualSize=PEAlign(image_section_header[i]->Misc.
VirtualSize,image_nt_headers->OptionalHeader.
SectionAlignment);AlignthePointerToRawDataandtheSizeOfRawDataofeachsectionbyFileAlignment:根据FileAlignment对齐每个节的PointerToRawData和SizeOfRawData:CollapseCopyCodeimage_section_header[i]->PointerToRawData=PEAlign(image_section_header[i]->PointerToRawData,image_nt_headers->OptionalHeader.
FileAlignment);image_section_header[i]->SizeOfRawData=PEAlign(image_section_header[i]->SizeOfRawData,image_nt_headers->OptionalHeader.
FileAlignment);CorrecttheSizeofImagebythevirtualsizeandthevirtualaddressofthelastsection:根据最后一个节的虚拟地址和虚拟大小修正SizeofImage:CollapseCopyCodeimage_nt_headers->OptionalHeader.
SizeOfImage=image_section_header[LastSection]->VirtualAddress+image_section_header[LastSection]->Misc.
VirtualSize;SettheBoundImportDirectoryheadertozero,asthisdirectoryisnotveryimportanttoexecuteaPEfile:清零导入目录头,这个目录对于可执行文件来说并无大碍:CollapseCopyCodeimage_nt_headers->OptionalHeader.
DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].
VirtualAddress=0;image_nt_headers->OptionalHeader.
DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].
Size=0;4.
4链接VC工程时的一些注意事项SetLinker->General->EnableIncrementalLinkingtoNo(/INCREMENTAL:NO).
设置链接器->常规->启用增量链接为否(/INCREMENTAL:NO).
Youcancomprehendthedifferencebetweenincrementallinkandno-incrementallinkbylookingatthefollowingpicture:通过下面的图片你会理解启用和关闭增量链接之间的区别:ToacquirethevirtualaddressofDynLoader(),weobtainthevirtualaddressofJMPpemaker.
DynLoaderintheincrementallink,butbyno-incrementallink,therealvirtualaddressisgainedbythefollowingcode:为了获得DynLoader()的虚拟地址,我们在增量链接下得到的是JMPpemaker.
DynLoader的虚拟地址,但是关闭增量链接,可以通过下面的代码获得真正的虚拟地址:CollapseCopyCodeDWORDdwVA=(DWORD)DynLoader;ThissettingismorecriticalintheincrementallinkwhenyoutrytofindthebeginningandendingoftheLoader,DynLoader(),byCPECryptor::ReturnToBytePtr():当你试图通过CPECryptor::ReturnToBytePtr()查找Loader,DynLoader()的起点或者终点时,这个设置显得更加危险:CollapseCopyCodevoid*CPECryptor::ReturnToBytePtr(void*FuncName,DWORDfindstr){void*tmpd;__asm{moveax,FuncNamejmpdfhjg:inceaxdf:movebx,[eax]cmpebx,findstrjnzhjgmovtmpd,eax}returntmpd;}5存储导入表数据并到达原始OEPRightnow,wesavetheOriginalOEPandalsotheImageBaseinordertoreachtothevirtualaddressofOEP.
IhavereservedafreespaceattheendofDynLoader()tostorethem,DynLoaderStep2.
现在,为了到达OEP的虚拟地址我们保存原始OEP以及映像基址.
我在DynLoader()的结尾保留了一块空闲空间来保存它们,DynLoader第2步.
PEMaker–第2步Downloadsourcefiles-58.
3KbDynLoader第2步CollapseCopyCode__stdcallvoidDynLoader(){_asm{DWORD_TYPE(DYN_LOADER_START_MAGIC)Main_0:PUSHAD//getbaseebpCALLMain_1Main_1:POPEBPSUBEBP,OFFSETMain_1MOVEAX,DWORDPTR[EBP+_RO_dwImageBase]ADDEAX,DWORDPTR[EBP+_RO_dwOrgEntryPoint]PUSHEAXRETN//>>JMPtoOriginalOEPDWORD_TYPE(DYN_LOADER_START_DATA1)_RO_dwImageBase:DWORD_TYPE(0xCCCCCCCC)_RO_dwOrgEntryPoint:DWORD_TYPE(0xCCCCCCCC)DWORD_TYPE(DYN_LOADER_END_MAGIC)}}Thenewfunction,CPECryptor::CopyData1(),willimplementthecopyoftheImageBasevalueandtheOffsetofEntryPointvalueinto8bytesoffreespaceintheloader.
新函数CPECryptor::CopyData1()将实现复制映像基址和入指针值的偏移到loader的8字节空间中.
5.
1恢复首次寄存器的上下文ItisimportanttorecovertheOriginalContextofthethread.
WehavenotyetdoneitintheDynLoaderStep2sourcecode.
WecanmodifythesourceofDynLoader()torepossessthefirstContext.
恢复原始线程的上下文是重要的.
我们在DynLoader第2步的源码中还没实现.
我们可以修改DynLoader()的源码来回收首次上下文.
CollapseCopyCode__stdcallvoidDynLoader(){_asm{DWORD_TYPE(DYN_LOADER_START_MAGIC)Main_0:PUSHAD//SavetheregisterscontextinstackCALLMain_1Main_1:POPEBP//GetBaseEBPSUBEBP,OFFSETMain_1MOVEAX,DWORDPTR[EBP+_RO_dwImageBase]ADDEAX,DWORDPTR[EBP+_RO_dwOrgEntryPoint]MOVDWORDPTR[ESP+1Ch],EAX//pStack.
Eax>JMPtoOriginalOEPDWORD_TYPE(DYN_LOADER_START_DATA1)_RO_dwImageBase:DWORD_TYPE(0xCCCCCCCC)_RO_dwOrgEntryPoint:DWORD_TYPE(0xCCCCCCCC)DWORD_TYPE(DYN_LOADER_END_MAGIC)}}5.
2恢复原始栈Wecanalsorecovertheoriginalstackbysettingthevalueofthebeginningstack+0x34totheOriginalOEP,butitisnotveryimportant.
Nevertheless,inthefollowingcode,IhaveaccomplishedtheloadercodebyasimpletricktoreachOEPinadditiontoredecoratingthestack.
YoucanobservetheimplementationbytracingusingOllyDbgorSoftICE.
我们也能恢复原始栈通过设置栈起始位置+距离原始OEP0x34字节的值,但是它不是非常重要.
虽然如此,下面的代码中,我已经实现了这个loader代码通过一个简单的诡计来到达OEP此外再调整了栈.
你可以通过使用OllyDbg或SoftICE跟踪观察这个实现.
CollapseCopyCode__stdcallvoidDynLoader(){_asm{DWORD_TYPE(DYN_LOADER_START_MAGIC)Main_0:PUSHAD//SavetheregisterscontextinstackCALLMain_1Main_1:POPEBPSUBEBP,OFFSETMain_1MOVEAX,DWORDPTR[EBP+_RO_dwImageBase]ADDEAX,DWORDPTR[EBP+_RO_dwOrgEntryPoint]MOVDWORDPTR[ESP+54h],EAX//pStack.
EipExceptions,youcanseeashortlistofdifferenttypesofexceptions.
程序运行到异常过滤,printf("3:InFilter\n");,当一个异常发生时,在样例中是INT3异常.
你也可以使用其它类型的异常.
在OllyDbg中,调试设置->异常,你可以看到一个不同类型异常的简短列表.
5.
3.
1实现异常处理WedesiretoconstructastructuredexceptionhandlerinordertoreachOEP.
Now,IthinkyouhavedistinguishedtheSEHinstallation,theexceptionraise,andtheexceptionexpressionfilter,byforegoingtheassemblycode.
Toestablishourexceptionhandlerapproach,weneedtocomprisethefollowingcodes:为了到达OEP我们想要创建一个结构化异常处理.
现在,通过前面的汇编代码我想你已经区别了SHE安装,异常抛出,和异常过滤.
为了确定我们的异常处理方法,我们需要包含下面的代码:SEH安装:CollapseCopyCodeLEAEAX,[EBP+_except_handler1_OEP_Jump]PUSHEAXPUSHDWORDPTRFS:[0]MOVDWORDPTRFS:[0],ESP抛出一个异常:CollapseCopyCodeINT3异常处理过滤器:CollapseCopyCode_except_handler1_OEP_Jump:PUSHEBPMOVEBP,ESP.
.
.
MOVEAX,EXCEPTION_CONTINUE_SEARCH//EXCEPTION_CONTINUE_SEARCH=0LEAVERETNSoweyearnformakingtheensuingC++codeinassemblylanguagetoinaugurateourenginetoapproachtheOffsetofEntryPointbySEH.
这样我们渴望创建接下来的C++代码用汇编语言来开创我们的引擎来实现通过SHE到达入口点偏移.
CollapseCopyCode__try//SEHinstallation{__asm{INT3//AnExceptionRaise}}__except(.
.
.
,EXCEPTION_CONTINUE_SEARCH){}//ExceptionhandlerexpressionfilterInassemblycode.
.
.
用汇编代码CollapseCopyCode;thestructuredexceptionhandler(SEH)installation;__try{LEAEAX,[EBP+_except_handler1_OEP_Jump]PUSHEAXPUSHDWORDPTRFS:[0]MOVDWORDPTRFS:[0],ESP;theraiseaINT3exceptionINT3INT3INT3INT3;};__except(.
.
.
;exceptionhandlerexpressionfilter_except_handler1_OEP_Jump:PUSHEBPMOVEBP,ESP.
.
.
MOVEAX,EXCEPTION_CONTINUE_SEARCH;EXCEPTION_CONTINUE_SEARCH=0LEAVERETN;,EXCEPTION_CONTINUE_SEARCH){}Theexceptionvalue,__except(.
.
.
,Value),determineshowtheexceptionishandled,itcanhavethreevalues,1,0,-1.
Tounderstandthem,refertothetry-exceptstatementdescriptionintheMSDNlibrary.
WesetittoEXCEPTION_CONTINUE_SEARCH(0),nottoruntheexceptionhandlerfunction,thereforebythisvalue,theexceptionisnotrecognized,issimplyignored,andthethreadcontinuesitscode-execution.
异常代码值,__except(.
.
.
,Value),决定了异常怎样处理,它有三个值,1,0,-1.
为了理解它们,参考MSDN库中的try-except语句描述.
我们设置它为EXCEPTION_CONTINUE_SEARCH(0),不运行异常处理函数,因此通过这个值,异常不会被认出,只被简单的略过,而且线程继续它的代码执行.
怎样实现SHE安装Asyouperceivedfromtheillustratedcode,theSEHinstallationisdonebytheFSsegmentregister.
MicrosoftWindows32bitusestheFSsegmentregisterasapointertothedatablockofthemainthread.
Thefirst0x1CbytescomprisetheinformationoftheThreadInformationBlock(TIB).
Therefore,FS:[00h]referstoExceptionListofthemainthread,Table3.
Inourcode,wehavepushedthepointerto_except_handler1_OEP_JumpinthestackandchangedthevalueofExceptionList,FS:[00h],tothebeginningofthestack,ESP.
例如你理解了例子代码,SHE安装是通过FS寄存器来完成.
微软32位Windows使用FS寄存器作为指向主线程的数据块指针.
第一个0x1C字节包含TIB的信息.
因此,FS:[00h]与主线程的ExceptionList相关联,表3.
在我们的代码中,我们已经压入指针到_except_handler1_OEP_Jump在栈中并改变ExceptionList的值,FS:[00h],到栈的起始,ESP.
线程信息块(TIB)CollapseCopyCodetypedefstruct_NT_TIB32{DWORDExceptionList;DWORDStackBase;DWORDStackLimit;DWORDSubSystemTib;union{DWORDFiberData;DWORDVersion;};DWORDArbitraryUserPointer;DWORDSelf;}NT_TIB32,*PNT_TIB32;表3-FS寄存器和线程信息块DWORDPTRFS:[00h]ExceptionListDWORDPTRFS:[04h]StackBaseDWORDPTRFS:[08h]StackLimitDWORDPTRFS:[0Ch]SubSystemTibDWORDPTRFS:[10h]FiberData/VersionDWORDPTRFS:[14h]ArbitraryUserPointerDWORDPTRFS:[18h]Self5.
3.
2通过调整线程上下文到达OEPInthispart,weeffectuateourperformancebyaccomplishingtheOEPapproach.
WechangetheContextofthethreadandignoreeverysimpleexceptionhandling,andletthethreadcontinuetheexecution,butintheoriginalOEP!
这部分中,我们通过到达OEP来完成我们的实现.
我们改变线程上下文并忽略所有的简单异常处理,并让线程继续执行,除非到达原始OEP!
Whenanexceptionhappens,thecontextoftheprocessorduringthetimeoftheexceptionissavedinthestack.
ByEXCEPTION_POINTERS,wehaveaccesstothepointerofContextRecord.
TheContextRecordhastheCONTEXTdatastructure,Table4,thisisthethreadcontextduringtheexceptiontime.
WhenweignoretheexceptionbyEXCEPTION_CONTINUE_SEARCH(0),theinstructionpointeraswellthecontextwillbesettoContextRecordinordertoreturntothepreviouscondition.
Therefore,ifwechangetheEipoftheWin32ThreadContexttotheOriginalOffsetofEntryPoint,itwillcomeclearlyintoOEP.
当发生一个异常时,处理器的上下文这时候会被保存到栈中.
通过EXCEPTION_POINTERS,我们可以访问到ContextRecord的指针.
ContextRecord有一个CONTEXT数据结构,表4,这是异常期间的线程上下文.
当我们使用EXCEPTION_CONTINUE_SEARCH(0)来忽略异常时,指示指针也将被上下文设置为ContextRecord为了返回到前面的状态.
因此,如果我们改变Win32线程上下文的Eip到原始入口点偏移,那将进入OEP无疑.
CollapseCopyCodeMOVEAX,ContextRecordMOVEDI,dwOEP;EAXOptionalHeader.
DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].
VirtualAddress;DWORDdwSize=image_nt_headers->OptionalHeader.
DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].
Size;TheVirtualAddressreferstostructuresbyIMAGE_IMPORT_DESCRIPTOR.
ThisstructurecontainsthepointertotheimportedDLLnameandtherelativevirtualaddressofthefirstthunk.
通过IMAGE_IMPORT_DESCRIPTOR参考VirtualAddress.
这个结构包含了指向导入DLL名字的指针和firstthunk的相对虚拟地址.
CollapseCopyCodetypedefstruct_IMAGE_IMPORT_DESCRIPTOR{union{DWORDCharacteristics;DWORDOriginalFirstThunk;};DWORDTimeDateStamp;DWORDForwarderChain;DWORDName;//theimportedDLLnameDWORDFirstThunk;//therelativevirtualaddressofthefirstthunk}IMAGE_IMPORT_DESCRIPTOR,*PIMAGE_IMPORT_DESCRIPTOR;Whenaprogramisrunning,theWindowstaskmanagersetsthethunksbythevirtualaddressofthefunction.
Thevirtualaddressisfoundbythenameofthefunction.
Atfirst,thethunksholdtherelativevirtualaddressofthefunctionname,Table5;duringexecution,theyarefixedupbythevirtualaddressofthefunctions,Table6.
当程序正在运行的时候,Windows任务管理器通过函数的虚拟地址设置thunk的值.
虚拟地址通过函数的名字被查找到.
首先,thunk保持函数名的相对虚拟地址,表5;执行期间,它们通过函数的虚拟地址被修正,表6.
表5–映像中的导入表IMAGE_IMPORT_DESCRIPTOR[0]OriginalFirstThunkTimeDateStampForwarderChainName_RVA------>"kernel32.
dll",0FirstThunk_RVA------>proc_1_name_RVA------>0,0,"LoadLibraryA",0proc_2_name_RVA------>0,0,"GetProcAddress",0proc_3_name_RVA------>0,0,"GetModuleHandleA",0.
.
.
IMAGE_IMPORT_DESCRIPTOR[1].
.
.
IMAGE_IMPORT_DESCRIPTOR[n]表6–虚拟内存中的导入表IMAGE_IMPORT_DESCRIPTOR[0]OriginalFirstThunkTimeDateStampForwarderChainName_RVA------>"kernel32.
dll",0FirstThunk_RVA------>proc_1_VAproc_2_VAproc_3_VA.
.
.
IMAGE_IMPORT_DESCRIPTOR[1].
.
.
IMAGE_IMPORT_DESCRIPTOR[n]WewanttomakeasimpleimporttabletoimportLoadLibrary(),andGetProcAddress()fromKernel32.
dll.
WeneedthesetwoessentialAPIfunctionstocoverotherAPIfunctionsinrun-time.
Thefollowingassemblycodeshowshoweasilywecanreachoursolution:我们要创建一个简单的导入表从Kernel32.
dl中导入LoadLibrary()和GetProcAddress().
在运行的时候我们需要这两个必要的API函数来得到其它的API函数.
下列汇编代码展示了在我们的解决方案中怎样简单地做到:CollapseCopyCode0101F000:00000000;OriginalFirstThunk0101F004:00000000;TimeDateStamp0101F008:00000000;ForwarderChain0101F00C:0001F034;Name;ImageBase+0001F034->0101F034->"Kernel32.
dll",00101F010:0001F028;FirstThunk;ImageBase+0001F028->0101F0280101F014:000000000101F018:000000000101F01C:000000000101F020:000000000101F024:000000000101F028:0001F041;ImageBase+0001F041->0101F041->0,0,"LoadLibraryA",00101F02C:0001F050;ImageBase+0001F050->0101F050->0,0,"GetProcAddress",00101F030:000000000101F034:'K''e''r''n''e''l''3''2''.
''d''l''l'000001F041:0000'L''o''a''d''L''i''b''r''a''r''y''A'000001F050:0000'G''e''t''P''r''o''c''A''d''d''r''e''s''s'00Afterrunning.
.
.
稍候继续CollapseCopyCode0101F000:00000000;OriginalFirstThunk0101F004:00000000;TimeDateStamp0101F008:00000000;ForwarderChain0101F00C:0001F034;Name;ImageBase+0001F034->0101F034->"Kernel32.
dll",00101F010:0001F028;FirstThunk;ImageBase+0001F028->0101F0280101F014:000000000101F018:000000000101F01C:000000000101F020:000000000101F024:000000000101F028:7C801D77;->Kernel32.
LoadLibrary()0101F02C:7C80AC28;->Kernel32.
GetProcAddress()0101F030:000000000101F034:'K''e''r''n''e''l''3''2''.
''d''l''l'000001F041:0000'L''o''a''d''L''i''b''r''a''r''y''A'000001F050:0000'G''e''t''P''r''o''c''A''d''d''r''e''s''s'00Ihavepreparedaclasslibrarytomakeeveryimporttablebyusingaclientstringtable.
TheCITMakerclasslibraryinitmaker.
h,itwillbuildanimporttablebysz_IT_EXE_stringsandalsotherelativevirtualaddressoftheimporttable.
我准备了一个类库用来创建每个导入表通过使用一个客户字符串表.
在itmaker.
h中的CITMaker类,将通过sz_IT_EXE_strings及导入表的相对虚拟地址来创建一个导入表.
CollapseCopyCodestaticconstchar*sz_IT_EXE_strings[]={"Kernel32.
dll","LoadLibraryA","GetProcAddress",0,,0,};WesubsequentlyemploythisclasslibrarytoestablishanimporttabletosupportDLLsandOCXs,sothisisagenerallibrarytopresentallpossibleimporttableseasily.
Thenextstepisclarifiedinthefollowingcode.
我在后面使用这个类来建立一个导入表以支持DLL和OCX,所以这是一个普通的库简单的呈现所有可能的导入表.
下面的代码使下一步将变得清晰.
CollapseCopyCodeCITMaker*ImportTableMaker=newCITMaker(IMPORT_TABLE_EXE);.
.
.
pimage_section_header=AddNewSection(".
xxx",dwNewSectionSize);//buildimporttablebythecurrentvirtualaddressImportTableMaker->Build(pimage_section_header->VirtualAddress);memcpy(pNewSection,ImportTableMaker->pMem,ImportTableMaker->dwSize);.
.
.
memcpy(image_section[image_nt_headers->FileHeader.
NumberOfSections-1],pNewSection,dwNewSectionSize);.
.
.
image_nt_headers->OptionalHeader.
DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].
VirtualAddress=pimage_section_header->VirtualAddress;image_nt_headers->OptionalHeader.
DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].
Size=ImportTableMaker->dwSize;.
.
.
deleteImportTableMaker;Theimporttableiscopiedatthebeginningofthenewsection,andtherelevantdatadirectoryisadjustedtotherelativevirtualaddressofthenewsectionandthesizeofthenewimporttable在新节的开始导入表就被复制,与之有关的数据目录被修正到新节的相对虚拟地址和新导入表的大小.
6.
2运行时使用API函数Atthistime,wecanloadotherDLLsandfindtheprocessaddressofotherfunctionsbyusingLoadLibrary()andGetProcAddress():这时,我们可以加载其它DLL和使用LoadLibrary()和GetProcAddress()查找其它函数在进程中的地址:CollapseCopyCodeleaedi,@"Kernel32.
dll"pushedimoveax,offset_p_LoadLibrarycall[ebp+eax]//LoadLibrary(lpLibFileName);movesi,eax//esi->hModuleleaedi,@"GetModuleHandleA"pushedipushesimoveax,offset_p_GetProcAddresscall[ebp+eax]//GetModuleHandle=GetProcAddress(hModule,lpProcName);IwanttohaveacompleteimportedfunctiontablesimilarinperformancedoneinarealEXEfile.
IfyoulookinsideaPEfile,youwilldiscoverthatanAPIcallisdonebyanindirectionjumpthroughthevirtualaddressoftheAPIfunction:我想要一个完整的导入函数表类似于在真正的EXE文件执行的那样.
如果你深入PE文件,你将发现一个API调用是通过一个API函数的虚拟地址跳转来实现的:JMPDWORDPTR[XXXXXXXX]CollapseCopyCode.
.
.
0101F028:7C801D77;VirtualAddressofkernel32.
LoadLibrary().
.
.
0101F120:JMPDWORDPTR[0101F028].
.
.
0101F230:CALL0101F120;JMPtokernel32.
LoadLibrary.
.
.
Itmakesiteasytoexpandtheotherpartofourprojectbythisperformance,soweconstructtwodatatables:firstforAPIvirtualaddresses,andthesecondfortheJMP[XXXXXXXX].
通过这样执行之后使得展开我们的工程的其它部分变得容易,所以我们构建两个数据表:第一个为API虚拟地址,第2个为JMP[XXXXXXXX]CollapseCopyCode#define__jmp_apibyte_type(0xFF)byte_type(0x25)__asm{.
.
.
_p_GetModuleHandle:dword_type(0xCCCCCCCC)_p_VirtualProtect:dword_type(0xCCCCCCCC)_p_GetModuleFileName:dword_type(0xCCCCCCCC)_p_CreateFile:dword_type(0xCCCCCCCC)_p_GlobalAlloc:dword_type(0xCCCCCCCC)_jmp_GetModuleHandle:__jmp_apidword_type(0xCCCCCCCC)_jmp_VirtualProtect:__jmp_apidword_type(0xCCCCCCCC)_jmp_GetModuleFileName:__jmp_apidword_type(0xCCCCCCCC)_jmp_CreateFile:__jmp_apidword_type(0xCCCCCCCC)_jmp_GlobalAlloc:__jmp_apidword_type(0xCCCCCCCC).
.
.
}Inthesucceedingcode,wehasconcludedourambitiontoinstallacustominternalimporttable!
(Wecannotcallitimporttable.
)在完成的代码中,我们已经实现了我们的抱负去安装一个定制的内置导入表!
(我们不能再叫它导入表.
)CollapseCopyCode.
.
.
leaedi,[ebp+_p_szKernel32]leaebx,[ebp+_p_GetModuleHandle]leaecx,[ebp+_jmp_GetModuleHandle]addecx,02h_api_get_lib_address_loop:pushecxpushedimoveax,offset_p_LoadLibrarycall[ebp+eax]//LoadLibrary(lpLibFileName);popecxmovesi,eax//esi->hModulepushedicall__strlenaddesp,04haddedi,eax_api_get_proc_address_loop:pushecxpushedipushesimoveax,offset_p_GetProcAddresscall[ebp+eax]//GetModuleHandle=GetProcAddress(hModule,lpProcName);popecxmov[ebx],eaxmov[ecx],ebx//JMPDWORDPTR[XXXXXXXX]addebx,04haddecx,06hpushedicall__strlenaddesp,04haddedi,eaxmoval,byteptr[edi]testal,aljnz_api_get_proc_address_loopincedimoval,byteptr[edi]testal,aljnz_api_get_lib_address_loop.
.
.
6.
3修正原始导入表Inordertoruntheprogramagain,weshouldfixupthethunksoftheactualimporttable,otherwisewehaveacorruptedtargetPEfile.
OurcodemustcorrectallofthethunksthesameasTable5toTable6.
Oncemore,LoadLibrary()andGetProcAddress()aidusinourefforttoreachourintention.
为了再次运行程序,我们应该修正真实导入表的thunk值,否则我们会有一个无效的PE文件.
我们的代码必须修正全部的thunk值就像表5到表6.
再次,LoadLibrary()和GetProcAddress()能帮助我们达到我们努力所达到的目的.
CollapseCopyCode.
.
.
movebx,[ebp+_p_dwImportVirtualAddress]testebx,ebxjz_it_fixup_endmovesi,[ebp+_p_dwImageBase]addebx,esi//dwImageBase+dwImportVirtualAddress_it_fixup_get_lib_address_loop:moveax,[ebx+00Ch]//image_import_descriptor.
Nametesteax,eaxjz_it_fixup_endmovecx,[ebx+010h]//image_import_descriptor.
FirstThunkaddecx,esimov[ebp+_p_dwThunk],ecx//dwThunkmovecx,[ebx]//image_import_descriptor.
Characteristicstestecx,ecxjnz_it_fixup_tablemovecx,[ebx+010h]_it_fixup_table:addecx,esimov[ebp+_p_dwHintName],ecx//dwHintNameaddeax,esi//image_import_descriptor.
Name+dwImageBase=ModuleNamepusheax//lpLibFileNamemoveax,offset_p_LoadLibrarycall[ebp+eax]//LoadLibrary(lpLibFileName);testeax,eaxjz_it_fixup_endmovedi,eax_it_fixup_get_proc_address_loop:movecx,[ebp+_p_dwHintName]//dwHintNamemovedx,[ecx]//image_thunk_data.
Ordinaltestedx,edxjz_it_fixup_next_moduletestedx,080000000h//.
IF(importbyordinal)jz_it_fixup_by_nameandedx,07FFFFFFFh//getordinaljmp_it_fixup_get_addr_it_fixup_by_name:addedx,esi//image_thunk_data.
Ordinal+dwImageBase=OrdinalNameincedxincedx//OrdinalName.
Name_it_fixup_get_addr:pushedx//lpProcNamepushedi//hModulemoveax,offset_p_GetProcAddresscall[ebp+eax]//GetProcAddress(hModule,lpProcName);movecx,[ebp+_p_dwThunk]//dwThunkmov[ecx],eax//correctionthethunk//dwThunk=>nextdwThunkadddwordptr[ebp+_p_dwThunk],004h//dwHintName=>nextdwHintNameadddwordptr[ebp+_p_dwHintName],004hjmp_it_fixup_get_proc_address_loop_it_fixup_next_module:addebx,014h//sizeof(IMAGE_IMPORT_DESCRIPTOR)jmp_it_fixup_get_lib_address_loop_it_fixup_end:.
.
.
7支持DLL和OCXNow,weintendtoincludethedynamiclinklibrary(DLL)andOLE-ActiveXControlinourPEbuilderproject.
SupportingthemisveryeasyifwepayattentiontothetwotimearrivalintotheOffsetofEntryPoint,therelocationtableimplementation,andtheclientimporttable.
现在,我们计划将DLL和OCX包含进我们的PEbuilder工程.
如果我们专注于两次进入入口点偏移,重定位表完成,和客户导入表,那么支持它们非常容易.
PEMaker–第4步Downloadsourcefiles-68.
6Kb7.
1两次进入OEPTheOffsetofEntryPointofaDLLfileoranOCXfileistouchedbythemainprogramatleasttwice:一个DLL文件或者一个OCX文件的入口点的偏移会被主程序触发至少两次.
Constructor:WhenaDLLisloadedbyLoadLibrary(),oranOCXisregisteredbyusingLoadLibrary()andGetProcAddress()throughcallingDllRegisterServer(),thefirstoftheOEParrivalisdone.
当一个DLL被LoadLibrary()载入时,或一个OCX通过调用DllRegisterServer()来注册并调用LoadLibrary()和GetProcAddress(),会首次进入OEP.
CollapseCopyCodehinstDLL=LoadLibrary("test1.
dll");CollapseCopyCodehinstOCX=LoadLibrary("test1.
ocx");_DllRegisterServer=GetProcAddress(hinstOCX,"DllRegisterServer");_DllRegisterServer();//ocxregisterDestructor:WhenthemainprogramfreesthelibraryusagebyFreeLibrary(),thesecondOEParrivalhappens.
当主程序使用FreeLibrary()释放库时,会再次进入OEP.
CollapseCopyCodeFreeLibrary(hinstDLL);CollapseCopyCodeFreeLibrary(hinstOCX);Toperformthis,Ihaveemployedatrick,thatcausesinthesecondtimeagain,theinstructionpointer(EIP)travelingtowardstheoriginalOEPbythestructuredexceptionhandler.
为了完成这个,我用了一点小计谋,当原因再次触发时,EIP通过结构化异常处理指向OEP.
CollapseCopyCode_main_0:pushad//savetheregisterscontextinstackcall_main_1_main_1:popebpsubebp,offset_main_1//getbaseebpsupportdll,ocx_support_dll_0:jmp_support_dll_1//nop;nop;//IMAGE_NT_HEADERSmovax,wordptr[edi+016h]//edi->image_nt_headers->FileHeader.
Characteristicstestax,IMAGE_FILE_DLLjz_support_dll_2movax,9090h//OptionalHeader.
DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].
VirtualAddress;DWORDdwSize=image_nt_headers->OptionalHeader.
DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].
Size;ByOllyDbg,wehavethesameasthefollowingforthe".
reloc"section,byusingtheLongHexviewermode.
Inthisexample,thebasevirtualaddressis0x1000andthesizeoftheblockis0x184.
通过OllyDbg,我们有同样的就像下列通过长整型Hex查看模式查看".
reloc".
在这个例子中,基虚拟地址为0x1000且块大小为0x184.
CollapseCopyCode008E1000:00001000000001843016300030403028008E1010:30683054308C308030AC309C30D830CC008E1020:30E030DC30E830E430F030EC310030F4008E1030:3120310D315F315031A431A031C031A8008E1040:31D031CC31F431EC31FC31F832043200008E1050:320C320832143210324C322C32583254008E1060:3260325C326832643270326C32B03274Itrelocatesthedatainthesubsequentvirtualaddresses:它在后来的虚拟地址重定位数据:CollapseCopyCode0x1000+0x0000=0x10000x1000+0x0016=0x10160x1000+0x0028=0x10280x1000+0x0040=0x10400x1000+0x0054=0x1054.
.
.
Eachpackageperformstherelocationbyusingconsecutive4bytesformitsinternalinformation.
Thefirstbytereferstothetypeofrelocationandthenextthreebytesaretheoffsetwhichmustbeusedwiththebasevirtualaddressandtheimagebasetocorrecttheimageinformation.
每一项通过使用它自身信息的连续的4字节完成重定位.
第一个字节指出了重定位的类型和接下来三个字节哪个是必须被使用带有基虚拟地址和映像基址修正映像信息.
typeoffset03000000是什么类型Thetypecanbeoneofthefollowingvalues:类型可以是下列值之一:IMAGE_REL_BASED_ABSOLUTE(0):noeffect.
未实现IMAGE_REL_BASED_HIGH(1):relocatebythehigh16bytesofthebasevirtualaddressandtheoffset.
重定位通过基虚拟地址的高16字节的偏移IMAGE_REL_BASED_LOW(2):relocatebythelow16bytesofthebasevirtualaddressandtheoffset.
重定位通过基虚拟地址的低16字节的偏移IMAGE_REL_BASED_HIGHLOW(3):relocatebythebasevirtualaddressandtheoffset.
重定位通过基虚拟地址的偏移重定位要做什么Byrelocation,somevaluesinsidethevirtualmemoryarecorrectedaccordingtothecurrentimagebasebythe".
reloc"sectionpackages.
通过重定位,一些值在虚拟内存中被修正通过被".
reloc"节打包的当前映像基址.
CollapseCopyCodemem[current_ImageBase+0x1000]=mem[current_ImageBase+0x1000]+delta_ImageBase;mem[current_ImageBase+0x1016]=mem[current_ImageBase+0x1016]+delta_ImageBase;mem[current_ImageBase+0x1028]=mem[current_ImageBase+0x1028]+delta_ImageBase;mem[current_ImageBase+0x1040]=mem[current_ImageBase+0x1040]+delta_ImageBase;mem[current_ImageBase+0x1054]=mem[current_ImageBase+0x1054]+delta_ImageBase;.
.
.
IhaveemployedthefollowingcodefromMorphinepackertoimplementtherelocation.
我从Morphine壳中使用了下面的代码来实现重定位.
CollapseCopyCode.
.
.
_reloc_fixup:moveax,[ebp+_p_dwImageBase]movedx,eaxmovebx,eaxaddebx,[ebx+3Ch]//edi->IMAGE_NT_HEADERSdelta_ImageBase=current_ImageBase-image_nt_headers->OptionalHeader.
ImageBasemovebx,[ebx+034h]//edx->image_nt_headers->OptionalHeader.
ImageBasesubedx,ebx//edx->reloc_correction//delta_ImageBaseje_reloc_fixup_endmovebx,[ebp+_p_dwRelocationVirtualAddress]testebx,ebxjz_reloc_fixup_endaddebx,eax_reloc_fixup_block:moveax,[ebx+004h]//ImageBaseRelocation.
SizeOfBlocktesteax,eaxjz_reloc_fixup_endleaecx,[eax-008h]shrecx,001hleaedi,[ebx+008h]_reloc_fixup_do_entry:movzxeax,wordptr[edi]//Entrypushedxmovedx,eaxshreax,00Ch//Type=Entry>>12movesi,[ebp+_p_dwImageBase]//ImageBaseanddx,00FFFhaddesi,[ebx]addesi,edxpopedx_reloc_fixup_HIGH://IMAGE_REL_BASED_HIGHdeceaxjnz_reloc_fixup_LOWmoveax,edxshreax,010h//HIWORD(Delta)jmp_reloc_fixup_LOW_fixup_reloc_fixup_LOW://IMAGE_REL_BASED_LOWdeceaxjnz_reloc_fixup_HIGHLOWmovzxeax,dx//LOWORD(Delta)_reloc_fixup_LOW_fixup:addwordptr[esi],ax//mem[x]=mem[x]+delta_ImageBasejmp_reloc_fixup_next_entry_reloc_fixup_HIGHLOW://IMAGE_REL_BASED_HIGHLOWdeceaxjnz_reloc_fixup_next_entryadd[esi],edx//mem[x]=mem[x]+delta_ImageBase_reloc_fixup_next_entry:incediincedi//Entry++loop_reloc_fixup_do_entry_reloc_fixup_next_base:addebx,[ebx+004h]jmp_reloc_fixup_block_reloc_fixup_end:.
.
.
7.
3构建特别的导入表InordertosupporttheOLE-ActiveXControlregistration,weshouldpresentanappropriateimporttabletoourtargetOCXandDLLfile.
为了支持OLE-ActiveXControl注册,我们应该为目标OCX和DLL文件呈献一个适当的导入表.
Therefore,Ihaveestablishedanimporttablebythefollowingstring:因此,我建立了一个由下列字符串组成的导入表:CollapseCopyCodeconstchar*sz_IT_OCX_strings[]={"Kernel32.
dll","LoadLibraryA","GetProcAddress","GetModuleHandleA",0,"User32.
dll","GetKeyboardType","WindowFromPoint",0,"AdvApi32.
dll","RegQueryValueExA","RegSetValueExA","StartServiceA",0,"Oleaut32.
dll","SysFreeString","CreateErrorInfo","SafeArrayPtrOfIndex",0,"Gdi32.
dll","UnrealizeObject",0,"Ole32.
dll","CreateStreamOnHGlobal","IsEqualGUID",0,"ComCtl32.
dll","ImageList_SetIconSize",0,0,};WithouttheseAPIfunctions,thelibrarycannotbeloaded,andmoreovertheDllregisterServer()andDllUregisterServer()willnotoperate.
InCPECryptor::CryptFile,IhavedistinguishedbetweenEXEfilesandDLLfilesintheinitializationofthenewimporttableobjectduringcreation:除了这些API函数外,其它库不能被加载,而且不能使用DllregisterServer()和DllUregisterServer().
在CPECryptor::CryptFile,我已经在新导入表目标初始化期间区分了EXE和DLL文件.
CollapseCopyCodeif((image_nt_headers->FileHeader.
Characteristics&IMAGE_FILE_DLL)==IMAGE_FILE_DLL){ImportTableMaker=newCITMaker(IMPORT_TABLE_OCX);}else{ImportTableMaker=newCITMaker(IMPORT_TABLE_EXE);}8PreservetheThreadLocalStorageByusingThreadLocalStorage(TLS),aprogramisabletoexecuteamultithreadedprocess,thisperformancemostlyisusedbyBorlandlinkers:DelphiandC++Builder.
WhenyoupackaPEfile,youshouldtakecaretokeepcleantheTLS,otherwise,yourpackerwillnotsupportBorlandDelphiandC++BuilderlinkedEXEfiles.
TocomprehendTLS,Ireferyoutosection6.
7oftheMicrosoftPortableExecutableandCommonObjectFileFormatSpecificationdocument,youcanobservetheTLSstructurebyIMAGE_TLS_DIRECTORY32inwinnt.
h.
通过使用TLS,一个程序能执行多线程的任务,这种实现多见于Borland链接器:Delphi和C++Builder.
当我们压缩一个PE文件时,你应该小心保证TLS的干净,否则,你的壳将不能支持BorlandDelphi和C++Builder链接生成的可执行文件.
要理解TLS,你可以参考6.
7节部分的MicrosoftPortableExecutableandCommonObjectFileFormatSpecification文档,你可以通过在winnt.
h中的IMAGE_TLS_DIRECTORY32来观察TLS结构.
CollapseCopyCodetypedefstruct_IMAGE_TLS_DIRECTORY32{DWORDStartAddressOfRawData;DWORDEndAddressOfRawData;DWORDAddressOfIndex;DWORDAddressOfCallBacks;DWORDSizeOfZeroFill;DWORDCharacteristics;}IMAGE_TLS_DIRECTORY32,*PIMAGE_TLS_DIRECTORY32;TokeepsafetheTLSdirectory,Ihavecopieditinaspecialplaceinsidetheloader:要保证TLS目录的安全,我把它复制到loader中一个特殊的地方:CollapseCopyCode.
.
.
_tls_dwStartAddressOfRawData:dword_type(0xCCCCCCCC)_tls_dwEndAddressOfRawData:dword_type(0xCCCCCCCC)_tls_dwAddressOfIndex:dword_type(0xCCCCCCCC)_tls_dwAddressOfCallBacks:dword_type(0xCCCCCCCC)_tls_dwSizeOfZeroFill:dword_type(0xCCCCCCCC)_tls_dwCharacteristics:dword_type(0xCCCCCCCC).
.
.
ItisnecessarytocorrecttheTLSdirectoryentryintheOptionalHeader:有必要在可选头中修正TLS目录入口:CollapseCopyCodeif(image_nt_headers->OptionalHeader.
DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].
VirtualAddress!
=0){memcpy(&pDataTable->image_tls_directory,image_tls_directory,sizeof(IMAGE_TLS_DIRECTORY32));dwOffset=DWORD(pData1)-DWORD(pNewSection);dwOffset+=sizeof(t_DATA_1)-sizeof(IMAGE_TLS_DIRECTORY32);image_nt_headers->OptionalHeader.
DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].
VirtualAddress=dwVirtualAddress+dwOffset;}9注入你的代码Wearereadytoplaceourcodeinsidethenewsection.
Ourcodeisa"HelloWorld!
"messagebyMessageBox()fromuser32.
dll.
我们已经准备好了放置我们的代码进新节中.
我们的代码是一个从user32.
dll中调用MessageBox()弹出的"HelloWorld!
"消息框CollapseCopyCode.
.
.
pushMB_OK|MB_ICONINFORMATIONleaeax,[ebp+_p_szCaption]pusheaxleaeax,[ebp+_p_szText]pusheaxpushNULLcall_jmp_MessageBox//MessageBox(NULL,szText,szCaption,MB_OK|MB_ICONINFORMATION);.
.
.
PEMaker–第5步Downloadsourcefiles-71.
7Kb10结论Bythisarticle,youhaveperceivedhoweasilywecaninjectcodetoaportableexecutablefile.
Youcancompletethecodebyusingthesourceofotherpackers,createapackerinthesamewayasYoda'sProtector,andmakeyourpackerundetectablebymixingupwithMorphinesourcecode.
Ihopethatyouhaveenjoyedthisbriefdiscussionofonepartofthereverseengineeringfield.
Seeyouagaininthenextdiscussion!
通过这篇文章,你已经认识到怎样轻易注入我们的代码到一个可执行文件.
你可以完善代码使之用以其他的壳,用这样的方法创建一个壳就像Yoda'sProtector,并用Morphine源码混淆使你的壳不能被检测出来.
我希望你喜欢上了逆向工程领域的一部分的简短的讨论.
下次讨论中再见吧!
licloud怎么样?licloud目前提供香港cmi服务器及香港CN2+BGP服务器/E3-1230v2/16GB内存/240GB SSD硬盘/不限流量/30Mbps带宽,$39.99/月。licloud 成立於2021年,是香港LiCloud Limited(CR No.3013909)旗下的品牌,主要提供香港kvm vps,分为精简网络和高级网络A、高级网络B,现在精简网络和高级网络A。现在...
这不端午节和大家一样回家休息几天,也没有照顾网站的更新。今天又出去忙一天没有时间更新,这里简单搜集看看是不是有一些商家促销活动,因为我看到电商平台各种推送活动今天又开始一波,所以说现在的各种促销让人真的很累。比如在前面我们也有看到PacificRack 商家发布过年中活动,这不在端午节(昨天)又发布一款闪购活动,有些朋友姑且较多是端午节活动,刚才有看到活动还在的,如果有需要的朋友可以看看。第一、端...
活动方案:美国洛杉矶 E5 2696V2 2核4G20M带宽100G流量20元/月美国洛杉矶E5 2696V2 2核4G100M带宽1000G流量99元/季香港CN2 E5 2660V2 2核2G30M CN2500G流量119元/季日本CN2E5 2660 2核2G30M CN2 500G流量119元/季美国300G高防 真实防御E5 2696V2 2核2G30M...
esp文件为你推荐
操作http企业cms我想给一个企业做个网站需要用到CMS 不知道什么CMS比较适合企业主要是产品模块强大linux防火墙设置在linux iptables怎么开启中国企业在线用什么软件查找中国所有企业名称360arp防火墙在哪谁知道360防火墙的arp防火墙文件在哪购物车在超市、商场中为什么需要使用购物车呢?厦门三五互联科技股份有限公司厦门三五互联怎么样?123456hd手机上有电话的标志,后面有个HD是什么意思最土团购程序团购网真实吗,流程是什么?地址栏图标网站添加地址栏图标代码怎么写?
免费注册网站域名 免费域名跳转 arvixe asp.net主机 idc评测网 服务器cpu性能排行 NetSpeeder 台湾谷歌网址 40g硬盘 北京双线机房 jsp空间 seednet 赞助 网站卫士 免费dns解析 drupal安装 免费邮件服务器 免备案cdn加速 存储服务器 asp空间 更多