吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 3413|回复: 13
收起左侧

[其他转载] (C++/ASM)不使用API获得所有加载DLL的函数入口

  [复制链接]
风扫春残雪 发表于 2020-6-30 02:40
老技术了,基本上加密壳人手一个吧……学习结束后暂时告一段落,把这一段程序扔上来记录一下。也方便以后用
主要使用的是c++ + 内联汇编。其实我是想用纯c++的,但是ntdef.h总是和windows.h/winnt.h冲突,只能引用一个太麻烦了。最后就还是用汇编写了。

这个功能的主要实现方法是fs:[0]永远指向TEB(线程环境块),通过读取TEB的0x30处,可以获得当前进程的进程环境块(PEB),PEB的0xC是进程的LDR,保存了所有加载过的DLL信息。
LDR中有三个字段指向了LDR_DATA_TABLE的双向链表,通过双向链表可以得到所有dll的加载基址和dll名称;

得到dll加载基址后,再根据加载入内存中相应dll的PE头结构,可以获取dll的输出表信息。对输出表进行遍历,就可以获得所有函数的入口VA和名称了。

这一部分程序忽略了只能按序号索引的地址,所以……就这样吧。东西都是老东西了,写出来练练手。
我说的比较粗糙,对相关知识比较迷茫的同学可以参考一下这几篇文章,我感觉写得非常好
https://www.52pojie.cn/thread-684432-1-1.html
https://www.52pojie.cn/thread-685272-1-1.html

最后放代码。内联汇编为主,就染色成ASM了。可惜这个染色器不支持//注释
[] 纯文本查看 复制代码
#include <ntdef.h>;
#include <iostream>;
#include <string>;

void GetAllFuncs(unsigned int* intEntry);

int main() {
    
    _UNICODE_STRING* lpBaseDllName = {};
    unsigned int* intBaseAddr = {};

    __asm {
        mov eax, fs: [030h] //TEB -> PEB 
        add eax, 0ch
        mov eax, [eax] //PEB -> LDR
        add eax, 01ch
        mov eax, [eax] // LDR -> InInitializationOrderModuleList
        mov edx, eax //Save the first entry
    LIST_ENTRY_RET:
        mov ecx, [eax + 08h] //DllBase(DOS HEADER)
        mov intBaseAddr, ecx
        lea ecx, [eax + 01ch]
        mov lpBaseDllName, ecx //*BaseDllName *Note, normally kernel32.dll is at the second turn.
        mov eax, [eax]
        cmp eax, edx
        je RETNOW
        pushad
    }
    std::wcout << "DllName: " << lpBaseDllName->Buffer << std::hex << ", Entry: " << intBaseAddr << std::endl;
    GetAllFuncs(intBaseAddr);
    _asm {
        popad
        jmp LIST_ENTRY_RET
        RETNOW:
    }
}


void GetAllFuncs(unsigned int *intEntry) {
    char* lpNameOfFunction = {};
    unsigned int* intAddrOfFunction = {};
    __asm {
        mov eax, intEntry
        mov ebx, [eax + 03ch] //DOS_HEADER.e_lfanew
        add eax, ebx
        //now eax points to PE
        mov edx, 078h // PE + 078h = DataDirectory in x86(See IMAGE_NT_HEADERS32 struct)
        mov bx, [eax + 018h] //Magic, 010Bh for x86, 020Bh for x64 (x86/64 for the HEADER only)
        cmp bx, 020Bh
        jnz x86_next
        add edx, 010h //IMAGE_NT_HEADERS64 has more 10bytes than HEADERS32
        x86_next :
        mov eax, [eax + edx] //Export Table DATA_DIRECTORY
        //mov eax,[ebx] //RVA of Export Table

        mov ebx, intEntry
        add ebx, eax //ebx points to IMAGE_EXPORT_DIRECTORY

        //mov ecx,[ebx + 018h] //NumberOfNames
        //mov eax,[ebx + 01ch] //AddressOfFunctions
        //mov edx,[ebx + 024h] //AddressOfNameOrdinals
        //[ebx + 020h] //AddressOfName
        xor edi, edi

    GO_ON_EXPORT :
        imul eax, edi, 4
        mov edx, [ebx + 020h] //RVA Address
        add edx, intEntry
        mov esi, [edx + eax] //AddressOfName
        add esi, intEntry
        mov lpNameOfFunction, esi

        imul eax, edi, 2
        mov edx, [ebx + 024h]
        add edx, intEntry
        movzx esi, word ptr[edx + eax] //AddressOfNameOrdinals[i]
        imul esi, esi, 4

        mov edx, [ebx + 01ch]
        add edx, intEntry
        mov ecx, [edx + esi]
        add ecx, intEntry
        mov intAddrOfFunction, ecx
        pushad
    }
    std::cout << "Name: " << lpNameOfFunction << ", Address: " << std::hex << intAddrOfFunction << std::endl;
    __asm{
        popad
        inc edi
        cmp edi, [ebx + 018h]
        jnz GO_ON_EXPORT
    }
}

免费评分

参与人数 5吾爱币 +12 热心值 +5 收起 理由
a245656350 + 1 + 1 干货就是让人这么心情愉悦
pizazzboy + 1 + 1 我很赞同!
K丶先生 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
qaz003 + 2 + 1 我去,刚醒就看到硬菜了。。超喜欢
苏紫方璇 + 7 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| 风扫春残雪 发表于 2020-6-30 12:09
q2510908331 发表于 2020-6-30 11:57
[md]内联汇编完全可以使用较少的汇编来获取主要结构

https://www.nirsoft.net/kernel_struct/vista/PEB. ...

谢谢!我也觉得定义一下会好看很多……一时脑抽(

没有使用结构主要是当时想用ntdef.h里面的_UNICODE_STRING读取dllname结构。如果引用包含有PE结构的<windows.h>的话,就重定义了……单独拎出来定义又懒(现在想来费力不讨好,就一个结构cp一下又不是很难)
其实真要偷懒的话不用_UNICODE_STRING,直接用wchar_t去读UNICODE_STRING后面的那个串是更好的策略
IBinary 发表于 2020-6-30 11:57
本帖最后由 q2510908331 于 2020-6-30 11:59 编辑

内联汇编完全可以使用较少的汇编来获取主要结构

https://www.nirsoft.net/kernel_struct/vista/PEB.html
https://www.nirsoft.net/kernel_struct/vista/TEB.html
https://www.nirsoft.net/kernel_struct/vista/LDR_DATA_TABLE_ENTRY.html

定义好结构在定义PE结构多好.  你这样写可读性差.不过如果学习内联汇编写法还行. 真正的要使用还是定义为结构.
遍历结构进行操作. 你这种作为ShellCode还是不错

lifz888 发表于 2020-6-30 08:35
蓝枫冰笛 发表于 2020-6-30 08:44
竟然是前排,仰望大佬
pizazzboy 发表于 2020-6-30 09:11
厉害,谢谢分享。
Xw丶小威 发表于 2020-6-30 09:14
前排支持。用到回来看。
future001 发表于 2020-6-30 09:32
不愧是大神,直接用汇编写了,我都没写过汇编
sxisir 发表于 2020-6-30 09:51
太吊了,完全看不懂
IBinary 发表于 2020-6-30 13:42
风扫春残雪 发表于 2020-6-30 12:09
谢谢!我也觉得定义一下会好看很多……一时脑抽(

没有使用结构主要是当时想用ntdef.h里面的_UNICODE_ ...

是的呀哈哈.你这样做的话 做ShellCode还行. 真要以后自己用自己都不爱维护的.
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-25 09:55

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表