I am using OllyDbg 2.01 and I walked through this tutorial to figure out how Call DLL export works. Even though it was written for another version of OllyDBG it work just fine. We should notice, that in example with USER32.dll OllyDBG detects number of input arguments, so I can change them from Call DLL export dialogue.

I decided to write my own DLL library in C++ in order to test OllyDBG functionality in a more detailed manner.

Here is a source code of my library.


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

#include <string>

namespace CPPLib

    class Functions

        static CPPLib_API void Identify();

        static CPPLib_API void GetText();

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


#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;


In this question my interest is in the function PrintText. It takes string as an input argument, show Message box with it and prints the same string in the console.

If I call this function from C++ program - it works just fine.

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

int main()
    std::string s = "USER INPUT";
    return 0;

Unlike in the example from tutorial, OllyDBG does not detect number of input arguments for my DLL.

function from user32.dll USER32.dll

CPPLib.dll CPPLib.dll

Moreover, even if I define it manually (e.g. choose Arg1 to be memory buffer 1) when calling that function it does not take what I wanted to be an argument. And there is no other way to change this argument as step into a function, find memory address to which it refers and change it there.

So my question is: Why does OllyDbg detect number of input arguments in functions (and allows to alter them easily) from USER32.dll and doesn't in my own DLL? How can I overcome this problem?

  • I'm not sure of the way you are loading, building your dll. Does yours also have a static library? In some instances dlls can be used as a static library and linked statically. Feb 24, 2017 at 7:15
  • Also see here msdn.microsoft.com/en-us/library/d91k01sh.aspx Feb 24, 2017 at 7:19
  • @marshalcraft , I was trying to make dynamic library, so I ended up following this tutorial link, because I though I was doing something wrong. From you link I clearly see, that "If you are not using the __declspec(dllexport) keyword to export the DLL's functions, the DLL requires a .def file.", so far I used it in my code.
    – aGGeRReS
    Feb 24, 2017 at 10:03
  • So whitch are you inquiring about, how to use dlls or how ollydbg? That seems to be a logical deductive step. Feb 24, 2017 at 11:47
  • @marshalcraft, I am inquiring about why OllyDBG does not see arguments for my own library, but for the e.g. user32.dll does.
    – aGGeRReS
    Feb 24, 2017 at 11:51

1 Answer 1


i compiled the src in commandline (no vs using ewdk)
and it appears ollydbg is able to identify the args and the call export seems to succeed here with some random crap thrown in for s

i assume you are aware std::string is a structure and not a plain string
you may need to properly craft a std::string and point the address of the std::string
for you to see it in messagebox in the argument field

well for whatever it is worth here is a screenshot of my dab with what was posted and its results

enter image description here


std::string is a structure as i mentioned

your s if you debugged your executable directly should be like this

0:000> dt -r9 s
Local var @ 0x22f984 Type std::basic_string<char,std::char_traits<char>,std::allocator<char> >*
   +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

so if you notice std::string contains a small performance optimization like if the string is less than 0x10 bytes it doesn't allocate memory but uses the buffer directly if the string is bigger than 0x10 bytes it allocates memory

it has a size and max size members at 0x10 and 0x14 from the start of buffer ie foo.cstr() you may need to properly set them see below two snap shots one for a bigger std::string and one for a smaller std::string

enter image description here

bigger string

enter image description here

you should recognize 4021c0 as loaddlls dump1 space

hope that helps

as to why ollydbg shows two args may be it is a bug in the olly engine

according to windbg it is only one parameter

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) 
  • 1
    Interesting. Do you have any idea why compiling from command line is different from one in the VS? I mean which options in the VS can affect the result?
    – aGGeRReS
    Feb 24, 2017 at 10:09
  • 1
    not sure check vs commandline in your project versus this cl /LD /W4 /Ox /Zi /analyze /EHsc cpplib.cpp /link /DEBUG /RELEASE %linklibs% cl /W4 /Ox /Zi /analyze /EHsc usedll.cpp /link /DEBUG /RELEASE %linklibs% i #defined CPPLIB_EXPORTS and UNICODE in cpplib.cpp and used #pragma comment ( lib ,"cpplib.lib") for the linking the executable with the lib file
    – blabb
    Feb 24, 2017 at 10:34
  • so far I realized that switching from debug to release mode solves my problem. Since it voidptr, it takes and displays only a first symbol of memory buffer. But this is much better, thank you.
    – aGGeRReS
    Feb 24, 2017 at 12:22
  • sorry for bothering you again. But I have been trying different things (e.g.define string argument as const std::string &) to be able to set it while debugging in OllyDbg with no success. You have said that > you may need to properly craft a std::string and point the address of the std::string but even though I stepped manually though all the function, I haven't found a way to set the whole string to be displayed in message box. BTW. Do you have any idea why OllyDbg shows two s:VOIDPTR arguments instead of one?
    – aGGeRReS
    Feb 27, 2017 at 9:52
  • edited the answer and added some info take a look
    – blabb
    Mar 6, 2017 at 18:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.