Sign in to follow this  
Followers 0
wraithdu

Compiling for machine code, need help

70 posts in this topic

#1 ·  Posted (edited)

I'll start off by saying I pretty much suck at actual programming, and my understanding of the compiling process is pretty basic. That said, what I'm trying to do is build machine code for a set of functions. I've built the DLL and it works, which is good. I'm using Codeblocks and TDM-GCC (for 64-bit). My usual process for machine code is to compile as a static library and dump (objdump.exe) the object file which outputs all the hex codes and assembly instructions.

The problem this time is that the functions call other functions from libuser32. These functions show up as calls to imports in the object, which I then assume are statically linked at linking time when the DLL is produced. What I need is everything in the one object file. Whether that's some type of linking, or function inlining, I don't know what to call it. But in the end I need the object file from which I can dump the machine code, and it must be self contained.

Some examples of what these imports look like.

from objdump (line 1f2)

000001e0 <__GetProcAddress>:
 1e0:   83 ec 1c                sub    $0x1c,%esp
 1e3:   8b 44 24 24             mov    0x24(%esp),%eax
 1e7:   89 44 24 04             mov    %eax,0x4(%esp)
 1eb:   8b 44 24 20             mov    0x20(%esp),%eax
 1ef:   89 04 24                mov    %eax,(%esp)
 1f2:   ff 15 00 00 00 00       call   *0x0
 1f8:   83 ec 08                sub    $0x8,%esp
 1fb:   83 c4 1c                add    $0x1c,%esp
 1fe:   c3                      ret    
 1ff:   90                      nop

From the compiler with the -S flag (line with *__imp__)

__GetProcAddress:
    subl    $28, %esp
    movl    36(%esp), %eax
    movl    %eax, 4(%esp)
    movl    32(%esp), %eax
    movl    %eax, (%esp)
    call    *__imp__GetProcAddress@8
    subl    $8, %esp
    addl    $28, %esp
    ret
    .p2align 4,,15
    .def    __LoadLibrary;  .scl    3;  .type   32; .endef

Any ideas or more info needed?

Edited by wraithdu

Share this post


Link to post
Share on other sites



#2 ·  Posted (edited)

The thing is your code needs offset to another function (from user32). These offsets are stored in import table when module is created (linker's job).

Considering your code will be written to dynamically allocated memory space there is no way for you to know exact offset because the address of your code will vary.

To work-around you can add parameter to your function and then pass argument that will be actuall address of the function that you intend to call. Usually there will be more of these functions so resorceful programmers pass address of GetProcAddress function and resolve addresses of other functions internally.

Edited by trancexx

♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites

I was thinking along those same lines while I was eating lunch. I was hoping not to have to modify the code too much, but it's a nice challenge. Thanks :)

Share this post


Link to post
Share on other sites

#4 ·  Posted (edited)

@trancexx

Ugh, head against the wall :( So I'm dynamically loading all the required pointers and my object no longer has an __imp__ function calls. Good. Damn thing is still crashing though. Would you mind taking a look if I zipped up the source files (only 2) and a test script? I fear I'm a bit out of my depth. Once again, the fully compiled DLL works, just not the machine code version.

Edited by wraithdu

Share this post


Link to post
Share on other sites

Sure, hit me.


♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites

#6 ·  Posted (edited)

Thank you a ton :) This is basically the load DLL from memory thing that Ward and Beege have posted, but I'm trying to get something working that I can then do a 64-bit build of as well. I've stripped the unnecessary stuff out of the DLL for now, and included the disassembly dump as well.

The example is setup to try the machine code or the DLL. You should be able to make out what to comment / uncomment.

Edited by wraithdu

Share this post


Link to post
Share on other sites

#7 ·  Posted (edited)

Are you sure you want to do this? Using a DLL is the preferred way to do this (that's why they were invented).

If you want to resolve your crashes, attach a debugger to your process and call DebugBreak() before entering your assembly, and step through it. The mistakes should be obvious. 

e: ollydbg even shows the current line of code while stepping through (if object files are available).

Also, who allocates your memorymodule (and the nested pointers inside)?

Edited by Shaggi

Ever wanted to call functions in another process? ProcessCall UDFConsole stuff: Console UDFC Preprocessor for AutoIt OMG

Share this post


Link to post
Share on other sites

wraithdu, there are no strings in your opcodes. You took opcode from .text section but it references data in other section through offsets (pointers) stored in some registers.
For example, you do this:

// get addresses of functions we need
    HMODULE kernel32 = getModuleHandle("kernel32.dll");

...But if you look at your opcodes you won't find string "kernel32.dll" anywhere.

This is easy to fix, do you have idea how?


♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites

ugh, AT&T assembly syntax needs to be thrown out the window.

Do yourself a favor and get objconv, use it with -fyasm or f-nasm and then one of those assemblers.

Besides what trancexx is on about (static data), you are also importing these functions:

realloc

memset

memcpy

free

Those need to be replaced with the appropriate kernel32 calls.

One of the more interesting projects I've done is to create a completely self-contained assembly object file without any need for even a GetProcAddress pointer.  Just needed to use the FS or GS segment to figure out the rest.  But thats another story..

Share this post


Link to post
Share on other sites

#10 ·  Posted (edited)

Thanks both of you. I'll take a look at the static data and those additional functions, as well as that other disassembler. My head needs a break for a bit, but I'll pick it back up over the weekend and let you know how it's going.

Speaking of those extra functions, is it ok to use GetProcAddress to get the pointers to msvcrt, or do I need to ditch the CRT runtimes altogether in favor of kernel32 calls? There's a call to _stricmp in there as well.

Edited by wraithdu

Share this post


Link to post
Share on other sites

Get rid of CRT runtime calls.  Without knowing what they internally call, it doesn't matter if you statically link to them or not - you'll have to track every single function and see what dependencies there are.  And this will change depending on which compiler or compiler version you use.

Share this post


Link to post
Share on other sites

One of the more interesting projects I've done is to create a completely self-contained assembly object file without any need for even a GetProcAddress pointer.  Just needed to use the FS or GS segment to figure out the rest.  But thats another story..

Every serious Windows programmer should be able to do that.

Still the method is not safe because in order to do it correctly you must take ownership of the critical section object whose pointer is saved to PEB. To do that you have to call EnterCriticalSection and if you do that then you have dependency on system functions.

I have never seen manually written code failing though.


♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites

If I try something in ASM I use AndyG's >AssembleIt.

On German forum there is also version 2...

 

Br,

UEZ


Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Share this post


Link to post
Share on other sites

Every serious Windows programmer should be able to do that.

Still the method is not safe because in order to do it correctly you must take ownership of the critical section object whose pointer is saved to PEB. To do that you have to call EnterCriticalSection and if you do that then you have dependency on system functions.

I have never seen manually written code failing though.

 

trancexx, who are you kidding?  "every serious Windows programmer"? hahah..  there aren't many 'serious' Windows programmers that even know what the PEB is. And they don't need to.  It was 'interesting' to me because I hadn't done it before and certainly not in straight Assembly.  Most half-assed assembly hackers need to compile C to object/asm file and then use an assembler, but they miss out on some nice tricks that can be done at the Assembly level.

Ah, and yes it is safe without use of EnterCriticalSection because kernel32.dll is one of the first permanently loaded modules in the module order list (after the executable and ntdll.dll).

Share this post


Link to post
Share on other sites

wraithdu,

For most CRT functions you can find replacements through Kernel32 or some 'tinyclib' libraries..

For string comparison, look at lstrcmpi and CompareString, among others

There are a few 'TinyCLib' libraries.  The most famous is by Matt Pietrek (see "Reduce EXE and DLL Size with LIBCTINY.LIB").  The most up-to-date version of this library is here - leepa-libctiny @ GitHub.  Also, there's the Tiny C Runtime Library @ CodeProject.

Hope that helps.  And if you can't figure out the strings thing, you can simply do something like this:

//char *myString = "MyString";   // uses Static string
char myString[9] = {'M','y','S','t','r','i','n','g', '\0'};  // builds string locally
1 person likes this

Share this post


Link to post
Share on other sites

trancexx, who are you kidding?  "every serious Windows programmer"? hahah..  there aren't many 'serious' Windows programmers that even know what the PEB is. And they don't need to.  It was 'interesting' to me because I hadn't done it before and certainly not in straight Assembly.  Most half-assed assembly hackers need to compile C to object/asm file and then use an assembler, but they miss out on some nice tricks that can be done at the Assembly level.

 

Ah, and yes it is safe without use of EnterCriticalSection because kernel32.dll is one of the first permanently loaded modules in the module order list (after the executable and ntdll.dll).

Perhaps we have different definitions of serious then.

♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites

totes fer sure ;)

Share this post


Link to post
Share on other sites

wraithdu, there are no strings in your opcodes. You took opcode from .text section but it references data in other section through offsets (pointers) stored in some registers.

For example, you do this:

// get addresses of functions we need
    HMODULE kernel32 = getModuleHandle("kernel32.dll");

...But if you look at your opcodes you won't find string "kernel32.dll" anywhere.

This is easy to fix, do you have idea how?

 

I thought I knew how... but I'm not sure. I did a full disassembly including the .rdata section. Basically I pulled everything out of the object using a hex editor from the beginning to the end, based on the output of objconv (thanks for that link Ascend4nt!!). But I'm not confident it's correct, as none of my calls to GetProcAddress are succeeding. I pass a handle to kernel32 and a pointer to GetProcAddress in my call to the function.

I have one other thing to try, but I don't have the time now. Am I on the right track with the strings, or do I need to do something more?

Share this post


Link to post
Share on other sites

wraithdu, did you miss my post about the strings?  You should keep locally-built strings (located on the stack) and pass pointers to those.  Where you have "kernel32.dll", instead put 'sKernel32DLL' and have this at the top of the function:

char sKernel32DLL[13] = {'k','e','r','n','e','l','3','2', '.', 'd', 'l', 'l', '\0'};  // builds string locally

Share this post


Link to post
Share on other sites

I did see that, and that was the other thing I was going to try when I had a chance. I was kinda hoping not to have to go that way, but whatever works.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0