zoukankan      html  css  js  c++  java
  • 壳的编写(1)-- 简介与搭建框架

    最近学习了壳,自己手动编写了简单的壳,功能比较简单,现在简单整理成笔记,供大家参考。个人能力有限,如有谬误,请不吝赐教,万分感谢。

    参考资料:《黑客免杀攻防》,看雪论坛等

    简介
           “壳”是一种现实比较常见的东西,比如:花生壳、瓜子壳等等。这些壳主要是用来保护其自身的果实的,要想吃到这些果实,我们就需要将其剥掉。在我们的软件行业也存在这样类似的东西,这种东西我们也称之为“壳”,我们自身的软件就类似于花生仁,而“壳”用来保护我们自身的软件,避免被其他人窥探。

    壳根据作用,一般分为两种:压缩壳、加密壳。无论哪种他们的原理大致是相同的。我们给自身软件加壳后就会产生新的软件,新的软件是由壳和原软件组成,在执行的时候,先执行壳,由壳对原程序进行解密并还原到内存中去,接着执行原来的程序。如下图:

     

    当我们将带壳的程序运行后,壳就会加载自己的API函数,然后对已知的加密区进行解密,对压缩进行解压,并按照PE结构将其释放到正确的内存位置上,并进行重定位,然后跳转到原程序的入口点(OEP),运行原程序。如图:

     

    搭建环境
    开发环境
    Win7x64 旗舰版
    vs2013
    010Edit6.03
    OD1.1(吾爱破解版)
    PEid0.94
    LordPE

    说明:
     我们想程序的界面与逻辑进行分开,这样可以使两者互不干扰。


    创建三个项目
    a、创建一个名称为PackBase的mfc项目,用于界面操作
    b、创建一个名称为Pack_Base的dll项目,编写加壳逻辑
    c、创建一个名称为Stub的dll项目,编写壳的信息

    a、创建一个名称为Pack Base的mfc项目
    界面如下:

    先给EditControl的"Read Only"属性设置为"True",并为其定义两个变量,一个是CString类型的m_pathStr,一个是CEditor类型的m_pathEdit。

             然后实现拖拽效果,将该对话框中的Accept Files属性设置为True,然后按Ctrl + Shift +X,添加 WM_DROPFILES消息。

     

    在OnDropFiles中添加如下代码:

    void CPackBaseDlg::OnDropFiles(HDROP hDropInfo)
    {
    // TODO: 在此添加消息处理程序代码和/或调用默认值
    
    CDialogEx::OnDropFiles(hDropInfo);
    CDialogEx::OnDropFiles(hDropInfo);
    //拖动单个文件的时候
    WCHAR wcStr[MAX_PATH];
    DragQueryFile(hDropInfo, 0, wcStr, MAX_PATH);//获得拖曳的文件的文件名 
    m_pathEdit.SetWindowText(wcStr); //将路基添加到文本编辑框中 
    
    DragFinish(hDropInfo); //拖放结束后,释放内存 
    UpdateData(TRUE); //将界面上的信息保存到变量中
    
    MessageBox(m_pathStr, m_pathStr, 0); //测试是否成功
    }
    

      


    再次给“浏览”按钮事件处理添加浏览文件并获取文件路径代码,如下:

    void CPackBaseDlg::OnBnClickedButton1()
    {
    UpdateData(TRUE);
    //设置要浏览文件的类型
    static TCHAR BASED_CODE szFilter[] = _T("可执行文件 (*.exe)|*.exe|")
    _T("DLL文件 (*.dll)|*.dll|")
    _T("All Files (*.*)|*.*||");
    
    CFileDialog fileDlg(TRUE, _T("exe"), _T(""),
    OFN_FILEMUSTEXIST | OFN_HIDEREADONLY, szFilter);
    
    if (fileDlg.DoModal() == IDOK)
    {	//将获取的路径信息赋给变量	m_pathStr = fileDlg.GetPathName();
    }
    //更新控件显示信息
    UpdateData(FALSE);
    }
    

      

    在“加壳”按钮的添加如下代码用于测试:

    void CPackBaseDlg::OnBnClickedButton2()
    {
    MessageBox(m_pathStr, m_pathStr, 0);
    }
    

      


    运行程序测试成功,如图:

    b、创建一个名称为Pack_Dll的加壳dll程序 

    在该工程中的Pack_Dll.h文件中定义一个导出方法Pack用于加壳操作。由于c++存在“名称粉碎机制”,所以要使用 extend "C" 不让改方法“名称粉碎”。如下:

    extern "C" PACK_DLL_API BOOL Pack(CString strPath);
    

      


    我们需要导入CString的头文件,我们为了后面的操作方便,我们将#include <afxwin.h>加入到stdafx.h文件中,由于冲突所以需要去掉文件中"#include <windows.h>"。

    在Pack_Dll.cpp文件中对Pack方法进行实现,我们只需要简单的测试下即可。

    BOOL Pack(CString strPath)
    {
    MessageBox(0, L"Pack", 0, 0);
    return TRUE;
    }
    

      


    为了项目能够正常编译,我们需要去掉用dllmain.cpp文件中的DllMain方法,同时将该项目的“运行库”设置为“多线程调试(/MTD)”,如下图:

     

    接下来实现界面工程和dll的关联,我们在MFC工程的加壳方法中调用刚刚写的Pack方法,修改代码如下:

    #include "../Pack_Dll/Pack_Dll.h"
    #pragma comment(lib,"../Debug/Pack_Dll.lib")
    
    void CPackBaseDlg::OnBnClickedButton2()
    {
    //MessageBox(m_pathStr, m_pathStr, 0);
    Pack(m_pathStr);
    }
    

      

    通过项目依赖项让两个项目关联,在Pack Base项目上点击右键的“生成依赖项”中“项目依赖项”,在“依赖项”的“依赖于”中选择“Pack_Dll”即可,如下图:

     

    编译运行Pack Base项目,效果如下:

     


    c、创建名称为Stub的dll的项目

    在Stub.h的文件中,编写两个按C语言的进行编译的函数fnGetStub和fnSetStub,代码如下:

    extern "C"
    {
    //获取和设置Stub
    STUB_API int fnGetStub(void);
    STUB_API void fnSetStub(int n);
    }
    在Stub.cpp文件中对其进行实现:
    // 这是导出函数示例。
    STUB_API int fnGetStub(void)
    {
    return nStub;
    }
    
    STUB_API void fnSetStub(int n)
    {
    nStub = n;
    }
    

      


    将项目Pack_dll项目和Stub关联起来,在Pack_dll项目上击右键的“生成依赖项”中“项目依赖项”,在“依赖项”的“依赖于”中选择“Stub”即可,此时项目就会形成了:Pack项目依赖于Pack_dll项目,而Pack_dll项目依赖于Stub项目。如下图:

     

    修改Pack_dll项目中的Pack方法,在Pack_dll项目中调用Stub项目中导出的方法,代码如下:

    typedef int(*FUNGetStub)(void);
    typedef void(*FUNSetStub)(int n);
    
    BOOL Pack(CString strPath)
    {
    HMODULE hMod = LoadLibrary(L"Stub.dll");
    FUNSetStub pfnSetStub = (FUNSetStub)GetProcAddress(hMod, "fnSetStub");
    
    pfnSetStub(1);
    
    FUNGetStub pfnGetStub = (FUNGetStub)GetProcAddress(hMod, "fnGetStub");
    
    if (pfnGetStub())
    {
    MessageBox(0,L"加壳成功",0,0);
    }
    return TRUE;
    }
    

      


    此时项目就会形成了:Pack项目依赖于Pack_dll项目,而Pack_dll项目依赖于Stub项目。

             运行项目Pack,运行成功如下图,证明我们项目的基础框架调通,我们接下来就可以去编写壳了。

     


    d、修改编译配置
    我们将生成的Debug版本的stub.dll加载到LordPE中,发现区段表中的第一个区段为.textbss,如果是这样的话就会影响我们的操作

    为了达到第一个区段为.text,我们需要将想Stub设置为Release版本。(选项配置管理器)

    然后,我们在使用LoadPE,查看Release版本Stub.dll的区段信息。


    为了后面调试方便,我们要将Stub项目的输出目录设置为Debug,这样就会让Stub.dll为Release版本,但是输出到Debug目录中。

     

    参考项目代码: 01Pack Base  http://download.csdn.net/detail/obuyiseng/9386931
    ————————————————
    版权声明:本文为CSDN博主「布衣僧」的原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/oBuYiSeng/article/details/50447540

  • 相关阅读:
    spark streaming 概述
    spark sql 的性能调优
    LeetCode 106. Construct Binary Tree from Inorder and Postorder Traversal (用中序和后序树遍历来建立二叉树)
    LeetCode 105. Construct Binary Tree from Preorder and Inorder Traversal (用先序和中序树遍历来建立二叉树)
    LeetCode 90. Subsets II (子集合之二)
    LeetCode 88. Merge Sorted Array(合并有序数组)
    LeetCode 81. Search in Rotated Sorted Array II(在旋转有序序列中搜索之二)
    LeetCode 80. Remove Duplicates from Sorted Array II (从有序序列里移除重复项之二)
    LeetCode 79. Word Search(单词搜索)
    LeetCode 78. Subsets(子集合)
  • 原文地址:https://www.cnblogs.com/luckywolfzyy/p/11384856.html
Copyright © 2011-2022 走看看