Sunday, November 29, 2009

Compiling and running Windows programs on Linux

While the title of this post could make you wonder why you ever want to do this, there is actually a scenario where this comes handy. Let's say you downloaded exploit code or for instance the sample source code of the Database hackers handbook. In both cases you may encounter source code that requires a Windows development environment to compile. While Microsoft offers free express editions for many of their development tools, you still need a copy of Windows somewhere.

Last week I decided to try a different route with MinGW, which is a port of GCC that can be used to develop native Windows applications. If you want to use MinGW under Linux you have to build a cross compiler. Historically this has been a difficult task. On Gentoo Linux however there is a package named crossdev. Once installed this package automates the task of building a cross compiler. With the following command you can build a MinGW cross compiler:

$ sudo crossdev -t i686-mingw32

Building the cross compiler may take some time. Once installed the following command could be tried to compile one of the source code samples from the Database hackers handbook:

$ i686-mingw32-gcc C2_2.cpp -o dbsnmp.exe

However, you will receive receive several errors:
C2_2.cpp: In function ‘int StartWinsock()’:
C2_2.cpp:83: error: ‘isalpha’ was not declared in this scope
C2_2.cpp: In function ‘int QueryDBSNMP(int)’:
C2_2.cpp:128: error: ‘con’ was not declared in this scope
C2_2.cpp:128: error: ‘nect’ was not declared in this scope
C2_2.cpp:134: error: invalid conversion from ‘unsigned char*’ to ‘const char*’
C2_2.cpp:134: error:   initializing argument 2 of ‘int send(SOCKET, const char*, int, int)’
C2_2.cpp:135: error: invalid conversion from ‘unsigned char*’ to ‘char*’
C2_2.cpp:135: error:   initializing argument 2 of ‘int recv(SOCKET, char*, int, int)’
C2_2.cpp:142: error: ‘PrintResponse’ was not declared in this scope
C2_2.cpp:143: error: invalid conversion from ‘unsigned char*’ to ‘const char*’
C2_2.cpp:143: error:   initializing argument 2 of ‘int send(SOCKET, const char*, int, int)’
C2_2.cpp:144: error: invalid conversion from ‘unsigned char*’ to ‘char*’
C2_2.cpp:144: error:   initializing argument 2 of ‘int recv(SOCKET, char*, int, int)’
C2_2.cpp:152: error: invalid conversion from ‘unsigned char*’ to ‘const char*’
C2_2.cpp:152: error:   initializing argument 2 of ‘int send(SOCKET, const char*, int, int)’
C2_2.cpp:153: error: invalid conversion from ‘unsigned char*’ to ‘char*’
C2_2.cpp:153: error:   initializing argument 2 of ‘int recv(SOCKET, char*, int, int)’
C2_2.cpp:166: error: invalid conversion from ‘unsigned char*’ to ‘const char*’
C2_2.cpp:166: error:   initializing argument 2 of ‘int send(SOCKET, const char*, int, int)’
C2_2.cpp:167: error: invalid conversion from ‘unsigned char*’ to ‘char*’
C2_2.cpp:167: error:   initializing argument 2 of ‘int recv(SOCKET, char*, int, int)’

The error on line 83, about the isalpha function can be fixed by including ctype.h. The error about line 128 are caused by the extra minus sign in the connect function name. Script kiddie protection, who knows? The rest of the errors could be fixed by casting (char *) the send and receive buffers. Trying to compile again leaves us with one error:

C2_2.cpp:143: error: ‘PrintResponse’ was not declared in this scope

This error is caused by a missing declaration of the PrintResponse() function at the top of the source file. Once that error is fixed we encounter linking errors:
/tmp/ccf47BD7.o:C2_2.cpp:(.text+0x125): undefined reference to `_WSACleanup@0'
/tmp/ccf47BD7.o:C2_2.cpp:(.text+0x158): undefined reference to `_WSAStartup@8'
/tmp/ccf47BD7.o:C2_2.cpp:(.text+0x18d): undefined reference to `_WSACleanup@0'
/tmp/ccf47BD7.o:C2_2.cpp:(.text+0x1b9): undefined reference to `_gethostbyname@4'
/tmp/ccf47BD7.o:C2_2.cpp:(.text+0x20c): undefined reference to `_inet_addr@4'
/tmp/ccf47BD7.o:C2_2.cpp:(.text+0x2cf): undefined reference to `_socket@12'
/tmp/ccf47BD7.o:C2_2.cpp:(.text+0x30a): undefined reference to `_htons@4'
/tmp/ccf47BD7.o:C2_2.cpp:(.text+0x32b): undefined reference to `_bind@12'
/tmp/ccf47BD7.o:C2_2.cpp:(.text+0x343): undefined reference to `_closesocket@4'
/tmp/ccf47BD7.o:C2_2.cpp:(.text+0x368): undefined reference to `_htons@4'
/tmp/ccf47BD7.o:C2_2.cpp:(.text+0x38d): undefined reference to `_connect@12'
/tmp/ccf47BD7.o:C2_2.cpp:(.text+0x3a5): undefined reference to `_closesocket@4'
/tmp/ccf47BD7.o:C2_2.cpp:(.text+0x3e2): undefined reference to `_send@16'
/tmp/ccf47BD7.o:C2_2.cpp:(.text+0x40d): undefined reference to `_recv@16'
/tmp/ccf47BD7.o:C2_2.cpp:(.text+0x424): undefined reference to `_closesocket@4'
/tmp/ccf47BD7.o:C2_2.cpp:(.text+0x476): undefined reference to `_send@16'
/tmp/ccf47BD7.o:C2_2.cpp:(.text+0x4a1): undefined reference to `_recv@16'
/tmp/ccf47BD7.o:C2_2.cpp:(.text+0x4b8): undefined reference to `_closesocket@4'
/tmp/ccf47BD7.o:C2_2.cpp:(.text+0x50a): undefined reference to `_send@16'
/tmp/ccf47BD7.o:C2_2.cpp:(.text+0x535): undefined reference to `_recv@16'
/tmp/ccf47BD7.o:C2_2.cpp:(.text+0x54c): undefined reference to `_closesocket@4'
/tmp/ccf47BD7.o:C2_2.cpp:(.text+0x58b): undefined reference to `_closesocket@4'
/tmp/ccf47BD7.o:C2_2.cpp:(.text+0x5c3): undefined reference to `_send@16'
/tmp/ccf47BD7.o:C2_2.cpp:(.text+0x5ee): undefined reference to `_recv@16'
/tmp/ccf47BD7.o:C2_2.cpp:(.text+0x605): undefined reference to `_closesocket@4'
/tmp/ccf47BD7.o:C2_2.cpp:(.text+0x626): undefined reference to `_closesocket@4'
collect2: ld returned 1 exit status

All these functions are part of winsock library on Windows. What we need to do now is locate winsock.h on the local file system (use the one in the mingw directory, when multiple are found) and add the following options to our compile command:


$ i686-mingw32-gcc C2_2.cpp -o dbsnmp.exe -L/usr/i686-mingw32/usr/include/ -lws2_32

Finally our source compiled and linked and now we can run it with wine:
$ wine dbsnmp.exe



    Oracle DBSNMP Tool

    C:\>dbsnmp.exe host status|stop

    David Litchfield
    davidl@ngssoftware.com
    4th June 2004

Yeah, a running program at last!

No comments:

Post a Comment