舒默哦 发表于 2020-6-27 01:12

[VC] 64位壳子编写

本帖最后由 舒默哦 于 2020-7-4 01:19 编辑

https://static.52pojie.cn/static/image/hrline/3.gif


更新:
x64壳子的编写源码放到github上了,地址https://github.com/shumo-e/64-github。
源码兼容x32编译,支持x32加壳。实现了IAT加密,添加了一些反调试,实现了反虚拟机的功能。
https://static.52pojie.cn/static/image/hrline/1.gif


0x01
感谢《加密与解密》第四版的作者。
我编写的64位壳子就是借助这本书,还不完善,只实现了对代码段的简单加密,等项目完成后,我会把源码和流程发布到github上,到时第一时间通知吾爱的兄弟们。

https://static.52pojie.cn/static/image/hrline/1.gif


0x02
加密与解密上的64位壳子的源码有些问题,我会把源码传上来,下面我贴哪些地方需要更改的:
void __declspec(naked) Start()
{
      _asm {
                pushfq
                call Start1()
                popfq
                jmp rax
                ret
      }
}

ULONG_PTRStart1()
{
      
      //获取kernel32基址      
      ULONGLONG dwBase = GetKernel32Addr();

      fnGetProcAddress pfnGetProcAddress = (fnGetProcAddress)MyGetProcessAddress();
      //获取API地址
      fnLoadLibraryA pfnLoadLibraryA = (fnLoadLibraryA)pfnGetProcAddress((HMODULE)dwBase, "LoadLibraryW");
      fnGetModuleHandleA pfnGetModuleHandle = (fnGetModuleHandleA)pfnGetProcAddress((HMODULE)dwBase, "GetModuleHandleW");
      fnVirtualProtect pfnVirtualProtect = (fnVirtualProtect)pfnGetProcAddress((HMODULE)dwBase, "VirtualProtect");
      HMODULE hUser32 = (HMODULE)pfnLoadLibraryA(L"user32.dll");
      HMODULE hKernel32 = (HMODULE)pfnGetModuleHandle(L"kernel32.dll");

      fnExitProcess pfnExitProcess = (fnExitProcess)pfnGetProcAddress(hKernel32, "ExitProcess");


      fnMessageBox pfnMessageBox = (fnMessageBox)pfnGetProcAddress(hUser32, "MessageBoxW");
      ////弹出信息框                        
      int nRet = pfnMessageBox(NULL, L"欢迎使用免费64位加壳程序,是否运行主程序?", L"Hello PEDIY", MB_YESNO);

      if (nRet == IDYES)
      {
                //修改代码段属性
                ULONGLONG dwCodeBase = g_stcParam.dwImageBase + (DWORD)g_stcParam.lpStartVA;
                DWORD dwOldProtect = 0;
                pfnVirtualProtect((LPVOID)dwCodeBase, g_stcParam.dwCodeSize, PAGE_EXECUTE_READWRITE, &dwOldProtect);
                XorCode();//解密代码
                pfnVirtualProtect((LPVOID)dwCodeBase, g_stcParam.dwCodeSize, dwOldProtect, &dwOldProtect);

                g_oep = (FUN)(g_stcParam.dwImageBase + g_stcParam.dwOEP);
                //跳回原始OEP
                return (ULONG_PTR)g_oep;
      }
      //退出程序
      pfnExitProcess(0);
}

上面这段代码在Stub的工程目录里。
我用的是intel编译器,可以支持x64内联汇编,没有intel编译器也没关系,,可以直接写shellcode,Start()函数字节不多,shellcode就那几十个字节。

https://static.52pojie.cn/static/image/hrline/1.gif

0x03
项目中要多次申请内存,为了防止内存泄漏,可以使用智能指针,但我感觉用起来别扭,所有写了一个自动释放内存的类:
#pragma once
#include <vector>
using namespace std;

class AllocMemory
{
      vector<char*>p;
      
public:
      virtual ~AllocMemory()
      {
                for (int i = 0; i < p.size(); i++)
                {
                        free(p);
                }
                p.clear();
      }

public:
      template<typename T>
      T auto_malloc( ULONG_PTR MAXSIZE)
      {
                T tmp = (T)malloc(MAXSIZE);
                memset((char*)tmp, 0, MAXSIZE);
                p.push_back((char*)tmp);
                return tmp;
      }


};

修复重定位表代码没用书里作者提供的,下面贴出代码:
/*////////////////////////////////////////////////////////////////
*※※*FullName:         PerformBaseRelocation
*※※*功能      :         修复重定位表
*※※*Returns:            无
*※※*Parameter:      char* buff,PE文件首地址
*※※*Parameter:      POINTER_TYPE Value,buff的基址与贴在内存中的地址的差值
*※※*Parameter:
*※※*Parameter:
*※※*Parameter:
*※※*         Author:                  LCH
*/////////////////////////////////////////////////////////////////;
void PE::PerformBaseRelocation(ULONG_PTR buff, ULONG_PTR Value)
{
      PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)buff;
      PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)(buff + pDosHeader->e_lfanew);

      //获取目录表头指针
      PIMAGE_DATA_DIRECTORY pDataDirectory = pNtHeader->OptionalHeader.DataDirectory;
      if (pDataDirectory.Size > 0)
      {
                PIMAGE_BASE_RELOCATION relocation = (PIMAGE_BASE_RELOCATION)((ULONG_PTR buff + pDataDirectory.VirtualAddress);
                while (relocation->VirtualAddress > 0)
                {
                        BYTE* dest = (PBYTE)((ULONG_PTR )buff + relocation->VirtualAddress);
                        WORD* relInfo = (PWORD)((ULONG_PTR )relocation + sizeof(IMAGE_BASE_RELOCATION));
                        for (DWORD i = 0; i < ((relocation->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / 2); ++i, ++relInfo)
                        {
                              DWORD *patchAddrHL;
#ifdef _WIN64
                              ULONGLONG *patchAddr64;//change comlete 64 bit address
#endif
               
                              ULONG_PTR type, offset;

                              //the upper 4 bits define the type of relocation
                              type = *relInfo >> 12;
                              //the lower 12 bits define the offset
                              offset = (*relInfo) & 0xFFF;

                              switch (type)
                              {
                              case IMAGE_REL_BASED_ABSOLUTE:
                                        //skip relocation
                                        break;
#ifdef _WIN64
                              case IMAGE_REL_BASED_DIR64://change comlete 64 bit address
                                       patchAddr64 = (ULONGLONG*)(dest + offset);
                                       *patchAddr64 += Value;
                                       break;
#endif                              
                              case IMAGE_REL_BASED_HIGHLOW://change comlete 32 bit address                                       
                                        patchAddrHL = (DWORD*)(dest + offset);
                                        *patchAddrHL += Value;
                                        break;                                                               
                              default:
                                        break;
                              }
                        }

                        //advance to next relocation block
                        relocation = PIMAGE_BASE_RELOCATION((char*)relocation + relocation->SizeOfBlock);
                }
      }

}

https://static.52pojie.cn/static/image/hrline/1.gif


0x04
结语:
x64加壳框架外观,程序我会上传。
加密与解密第四版配套源码链接:
链接:https://pan.baidu.com/s/1hjAxUCsF6wiQl0TlKvCwvA 提取码:rfq6

风之暇想 发表于 2020-6-30 20:05

舒默哦 发表于 2020-6-30 10:49
我写的兼容32位和64位的哦,版主大人

{:301_997:}兼容性有待提高

cpj1203 发表于 2020-6-28 11:12

厲害!拍拍手。

netspirit 发表于 2020-6-27 01:36

感觉好厉害。。。。

王兰花秀丽 发表于 2020-6-27 01:40

虽然没怎么看懂,但是不妨碍我夸你厉害

拉玛西亚 发表于 2020-6-27 04:02

书我存了,谢谢分享了

Rodriguezs 发表于 2020-6-27 07:34

厉害了我的哥

yiting8 发表于 2020-6-27 11:37

大佬,书可以共享一下吗?

gh0st_ 发表于 2020-6-27 15:47

感谢分享

htpidk 发表于 2020-6-27 15:52

可以的,我也在准备写壳

舒默哦 发表于 2020-6-28 14:16

yiting8 发表于 2020-6-27 11:37
大佬,书可以共享一下吗?

链接:https://pan.baidu.com/s/1BG8Foq5ComqNbkFbAJ2DCQ
提取码:khqa
页: [1] 2 3
查看完整版本: [VC] 64位壳子编写