在 OllyDBG 中调用 DLL 导出

逆向工程 ollydbg 调试 dll 职能
2021-07-05 12:31:21

我使用的是 OllyDbg 2.01,我通过本教程了解了调用 DLL 导出的工作原理。即使它是为另一个版本的 OllyDBG 编写的,它也能正常工作。我们应该注意到,在 USER32.dll 的例子中,OllyDBG 检测输入参数的数量,所以我可以从调用 DLL 导出对话框中更改它们。

我决定用 C++ 编写自己的 DLL 库,以便更详细地测试 OllyDBG 的功能。

这是我的图书馆的源代码。

CPPlib.h

#pragma once
#ifdef CPPLib_EXPORTS  
#define CPPLib_API __declspec(dllexport)   
#else  
#define CPPLib_API __declspec(dllimport)   
#endif  

#include <string>

namespace CPPLib
{

    class Functions
    {
    public:

        static CPPLib_API void Identify();


        static CPPLib_API void GetText();


        static CPPLib_API void PrintText(std::string& s);
    };
}


CPPLib.cpp

#include "stdafx.h"  
#include "CPPLib.h"  
#include <iostream>
#include <windows.h>

namespace CPPLib
{
    void Functions::Identify()
    {
        std::cout << "This is a CPPlib \r\n";
    }

    void Functions::GetText()
    {
        std::cout << "This is a random text from CPPlib \r\n";
    }

    std::wstring s2ws(const std::string& s)
    {
        int len;
        int slength = (int)s.length() + 1;
        len = MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, 0, 0);
        wchar_t* buf = new wchar_t[len];
        MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, buf, len);
        std::wstring r(buf);
        delete[] buf;
        return r;
    }

    void Functions::PrintText(std::string& s)
    {
        std::wstring stemp = CPPLib::s2ws(s);
        LPCWSTR result = stemp.c_str();

        MessageBox(0, result, (LPCWSTR)L"MessageBox caption", MB_OK);

        std::cout << "This is a user input text: " << s;
    }


}

在这个问题中,我的兴趣在于函数PrintText它将字符串作为输入参数,用它显示消息框并在控制台中打印相同的字符串。

如果我从 C++ 程序调用这个函数 - 它工作得很好。

#include "stdafx.h"
#include "CPPLib.h"
#include <string>

int main()
{
    CPPLib::Functions::Identify();
    CPPLib::Functions::GetText();
    std::string s = "USER INPUT";
    CPPLib::Functions::PrintText(s);
    return 0;
}

与教程中的示例不同,OllyDBG 不会检测我的 DLL 的输入参数数量。

来自 user32.dll 的函数 用户32.dll

CPPLib.dll CPPLib.dll

此外,即使我在调用该函数时手动定义它(例如选择 Arg1 作为内存缓冲区 1),它也不会采用我想要的参数。并且没有其他方法可以将这个参数更改为进入函数的步骤,找到它所引用的内存地址并在那里更改它。

所以我的问题是:为什么 OllyDbg 从 USER32.dll 检测函数中的输入参数数量(并允许轻松更改它们),而不是在我自己的 DLL 中?我怎样才能克服这个问题?

1个回答

我在命令行中编译了 src(没有与使用 ewdk 相比)
,看起来 ollydbg 能够识别 args 并且调用导出似乎在这里成功,并为 s 抛出了一些随机废话

我假设你知道 std::string 是一个结构而不是一个普通的字符串
你可能需要正确地制作一个 std::string 并指向 std::string 的地址
以便你在参数字段的消息框中看到它

好吧,无论它值多少钱,这里都是我的轻拍的截图,其中包含发布的内容及其结果

在此处输入图片说明


编辑

std::string 是我提到的结构

如果你直接调试你的可执行文件,你的 s 应该是这样的

0:000> dt -r9 s
Local var @ 0x22f984 Type std::basic_string<char,std::char_traits<char>,std::allocator<char> >*
0x0022f98c
   +0x000 _Mypair          : std::_Compressed_pair<std::_Wrap_alloc<std::allocator<char> >,std::_Str
ing_val<std::_Simple_types<char> >,1>
      +0x000 _Myval2          : std::_String_val<std::_Simple_types<char> >
         +0x000 _Bx              : std::_String_val<std::_Simple_types<char> >::_Bxty
            +0x000 _Buf             : [16]  "USER INPUT"
            +0x000 _Ptr             : 0x52455355  "--- memory read error at address 0x52455355 ---"
            +0x000 _Alias           : [16]  "USER INPUT"
         +0x010 _Mysize          : 0xa
         +0x014 _Myres           : 0xf
   =6e2a0000 npos             : 0x905a4d
0:000>

所以如果你注意到 std::string 包含一个小的性能优化,比如如果字符串小于 0x10 字节,它不会分配内存,但如果字符串大于 0x10 字节,它会直接使用缓冲区分配内存

从缓冲区开始,它在 0x10 和 0x14 处有一个 size 和 max size 成员,即 foo.cstr() 您可能需要正确设置它们,请参见下面的两个快照,一个用于较大的 std::string,另一个用于较小的 std: :细绳

在此处输入图片说明

更大的字符串

在此处输入图片说明

您应该将 4021c0 识别为 loaddlls dump1 空间

希望有帮助

至于为什么ollydbg显示两个args可能是olly引擎中的一个错误

根据windbg,它只是一个参数

0:000> .fnent .
Debugger function entry 01e40268 for:
(6e2a10e0)   cpplib!CPPLib::Functions::PrintText   |  (6e2a1180)   cpplib!std::basic_string<wchar_t,
std::char_traits<wchar_t>,std::allocator<wchar_t> >::~basic_string<wchar_t,std::char_traits<wchar_t>
,std::allocator<wchar_t> >
Exact matches:
    cpplib!CPPLib::Functions::PrintText (class std::basic_string<char,std::char_traits<char>,std::al
locator<char> > *, class std::basic_string<char,std::char_traits<char>,std::allocator<char> > *)

OffStart:  000010e0
ProcSize:  0x9d
Prologue:  0x29
Params:    0n1 (0x4 bytes) <------------------------
Locals:    0n10 (0x28 bytes) 
Non-FPO
0:000>