初来看雪,发现如果靠挂机拿邀请码的话,貌似不靠谱...
拿出最近所学的东西,希望能得到版主的肯定.
错误之处,请高手不吝赐教,我等小菜,不胜感激~
看了 玩命 大牛的系列贴,发现“添加新节”中的程序编译不过,很困惑。于是拜读看雪大神的《加密与解密技术》,发现编译倒是通过了,连接也通过了,得到的程序却运行出错...
没招,开始一行一行理解,一共1708行.
总结一下难点:
1.壳中函数的重定位
2.pe加载器原理
加壳关键步骤(简略版):
...--->定位到最后section_table的结束--->在新的28h中写入关于壳的一些信息(注意SECTION对齐长度)--->numberofsection+1--->修改OEP,SizeOfImage--->写入壳--->...
其实,加区段只是加壳的整体思路,加密,加花,反dump之后,才能称得上真正的壳。
(压缩壳见附件)
使用说明:
1.将下载的附件改后缀为“.exe"
2. 将需加壳文件放入E盘,并改名为test.exe,运行本程序即可
功能:压缩,加花
(另:想看源码的,直接用 OD 看~~)
关键代码c语言表示如下:
void addshell()
{
DWORD *ReadBufer;
DWORD NumberOfBytesW;
pushad;
if(IsCreateBak==1h)
{
CreateBakFile(FileName);
}
HANDLE hFile=CreateFile(FileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,0, 3, FILE_ATTRIBUTE_NORMAL,NULL);
if(hFile==INVALID_HANDLE_VALUE)
{
cout<<"CreateFile() error"<<endl;
}
SetFilePointer(hFile, 3ch, NULL, FILE_BEGIN);
ReadFile(hFile,ReadBuffer, 4h,&NumberOfBytesRW, NULL);
//**********取文件映象大小,申请内存
SetFilePointer(hFile, 50h, NULL, FILE_BEGIN);
ReadFile(hFile,PeImageSize, 4h,NumberOfBytesRW, NULL);
MapOfFile=VirtualAlloc(NULL, PeImageSize, MEM_COMMIT, PAGE_READWRITE);
//**********取PE头大小,读入PE头
SetFilePointer(hFile, (&ReadBufer+84), NULL, FILE_BEGIN);
ReadFile(hFile, ReadBuffer, 4h, &NumberOfBytesRW, NULL);
SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
ReadFile(hFile, MapOfFile, ReadBuffer, &NumberOfBytesRW, NULL);
//*************
PeHeadBase=MapOfFile+ReadBuffer;
//**********取PE文件的一些信息
PeImageBase=(PIMAGE_NT_HEADERS)PeHeadBase.OptionalHeader.ImageBase;
//**********读入各个区块,并对区块资料取整
FileAlignment=(PIMAGE_NT_HEADERS)PeHeadBase.OptionalHeader.FileAlignment;
if(IsFileAlignment200 == 1)
{
FileAlignment=200h;
(PIMAGE_NT_HEADERS)PeHeadBase.OptionalHeader.FileAlignment=200h;
}
SectionAlignment=(PIMAGE_NT_HEADERS)PeHeadBase.OptionalHeader.SectionAlignment;
SecTableBase=(PIMAGE_SECTION_TABLE)(PeHeadBase+(PIMAGE_NT_HEADERS)PeHeadBase.FileHeader.SizeOfOptionalHeader+18h);
for(int i=0;i<(DWORD)((PIMAGE_NT_HEADERS)PeHeadBase.FileHeader.NumberOfSections);i++)
{
SetFilePointer( hFile, (PIMAGE_SECTION_TABLE)SecTableBase.PotinterToRawData, NULL, FILE_BEGIN); //区块文件偏移
ReadFile( hFile, (PIMAGE_SECTION_TABLE)SecTableBase.VirtualAddress + MapOfFile, (IMAGE_SECTION_TABLE)SecTableBase.SizeOfRawData, ADDR NumberOfBytesRW, NULL); //区块映象偏移->区块文件大小
SecTableBase.VirtualSize=GetIntegral((PIMAGE_SECTION_TABLE)SecTableBase.VirtualSize,SectionAlignment); //区块映象大小
&SecTableBase += 28h; //28h==sizeof(IMAGE_SECTION_TABLE)
}
AddLine(M_ReadFileOK);
PeImageSize=GetIntegral(PeImageSize,SectionAlignment);
(PIMAGE_NT_HEADERS)PeHeadBase.OptionalHeader.SizeOfImage=PeImageSize;
//***********压缩
lpPackBuffer=VirtualAlloc(NULL, 100000h, MEM_COMMIT, PAGE_READWRITE);
hFile=CreateFile(FileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,0,CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,NULL);
PackFile();
//*************处理外壳并写入
MapOfShell=VirtualAlloc(NULL, 20000h, MEM_COMMIT, PAGE_READWRITE);
MapOfShellUsed=DisposeShell();
WriteFile(hFile,MapOfShell ,MapOfShellUsed,$, NULL); //$(esp) defines current position!!!
//*******清空段名吗?
if(IsClsSecName == 1)
{
ClsSectionName();
}
//***********重写文件头
SetFilePointer(hFile, 0h, NULL, FILE_BEGIN);
WriteFile(hFile,MapOfFile ,PeHeadSize, NumberOfBytesRW, NULL);
//***********写入额外代码
SetFilePointer(hFile, 0h, NULL, FILE_END);
WriteFile(hFile,MapOfSData,MapOfSDataUsed,ADDR NumberOfBytesRW, NULL);
//***********加密完成,清理
CloseHandle(hFile);
VirtualFree(lpPackBuffer, 0, MEM_RELEASE);
VirtualFree(MapOfFile, 0, MEM_RELEASE);
if(MapOfCodeProt != 0)
{
VirtualFree(MapOfCodeProt, 0, MEM_RELEASE);
}
if(MapOfImpProt != 0)
{
VirtualFree(MapOfImpProt, 0, MEM_RELEASE);
}
if(MapOfPackRes != 0)
{
VirtualFree(MapOfPackRes, 0, MEM_RELEASE);
}
if(MapOfSData != 0)
{
VirtualFree(MapOfSData, 0, MEM_RELEASE);
}
for(i=0;i<FileDataEnd-hFile;i++)
{
*(&file+i)=0;
}
return;
}
[课程]Linux pwn 探索篇!