Flag: Tornado! Hurricane!

Blogs >> anonymouse's Blog

Created: Monday, July 9 2007 13:21.28 CDT  
Printer Friendly ...
compiling windows executable with DDK
Author: anonymouse # Views: 20288

now why in the world would anyone use ddk for compiling usermode executables when vc borland  and many other compilers and linkers exist  

no idea may be iam bit of eccentric
and i thought ill do it :)

anyway this blog entry is more of my own sadistic endevours trying to compile a simple helloworld console app
a simple messagebox windows gui app

i downloaded the 1830_usa.ddk (3790.1830) (230 mb iso) you got hint no 1 its more about size

the vc express 2005 free iso is about 500 mb and from google i gathered it simply needs another terrabyte of psdk and other assorted downloads to compile a simple hello world

and it looked from google that this ddk has the same or similar compiler cl.exe and linker and also came with almost all headers included in 230 mb
and i got hooked and downlaoded this iso

used isobuster to extract the objects and ran the setup.exe

it installed in my xp-sp1 (no dot net ) without a hitch
lucky me

i whistled and thought ill see my hello world in next five minutes :)

but five minutes my foot says ddk :) you need fifty hours
to simply understand the build bilch bitch whatever it is

i wrote a simple hello world

#include <stdio.h>

int main (void)
{
        printf( "hello test with ddk\n");
        return 0;
}


did start -> run ->developmentkits->w2kfreebuild
Windows 2000 Free Build Environment
and in the cmd window typed in build :)

it didnt build anything and the error log was simply saying checking dependencies and thats it :) checking what dependency who knows

time to hit google  

google simply has no relevent information about compiling windows user mode executables with  ddk (not in 96,me,nt,w2k,or wxp)

i found my first easy to understand driver compiling tutorial at  catch22.net by james

[url]
http://www.catch22.net/tuts/kernel1.asp
[/url]

it needs two extra files sources and makefile

well no problem create them and copy paste the relevent details from that tut

i saw it was driver so i chenged it to exe instead of driver in sources

now type in build the srror log says targettype not blah blah

hitting google again for targettype yields nothing much
so its back to opening the setenv , makefile.def -> which reditrects to makefile.new and parsing through the macros
and i find one needs PROGRAM for target type

my sources now

TARGETNAME=test
TARGETPATH=obj
TARGETTYPE=PROGRAM

SOURCES=test.c


now it says it want main to be declared as __cdecl

change test.c


#include <stdio.h>

int __cdecl main (void)
{
        printf( "hello test with ddk\n");
        return 0;
}


now it cant find _printf :( wtf
look around in src directory all of them uses _tprintf() with tchar.h included

but i dont want _tprintf whatever safe and secutre and extra locking  it may be having i want printf

also it cant find _ntprocessstartup@gs4

googling for ntprocessstartup yields one blog entry by one assarbad
who insists one needs to turn off bufferoverflow checks
with some lines in sources or do ifndef blocks to include some compiler satisfying code to fool this error off

[url]
http://blog.assarbad.net/20060708/windows-2003-sp1-ddk-with-a-little-annoyance/
[/url]

now im not going to give up and what doess  little changes
take just time so lets wake a few more hours in the night

but doing those changes simply dont yield a result

it still cant find printf

i change the lib paths to $(SDK_LIBRARY_PATH) etc etc
nada no result

lets grep the inc directory for printf yes it exists
so why cant this ddk find it ?

ok may be w2k is buggy lets build it in wxp free ,
w2k3 free

nope no printf

and finally after battling through the maze of cryptic .bats and makedefs

i found that you need to add these lines to sources file


TARGETNAME=test
TARGETPATH=obj
TARGETTYPE=PROGRAM

SOURCES=test.c


UMTYPE=console
UMBASE=0x00400000
UMENTRY=main


and it simply compiles file and produces an exe that works :) with a stripped (publics only) pdb

the working source , sources , makefile details



#include <stdio.h>

int __cdecl main (void)
{
        printf( "hello test with ddk\n");
        return 0;
}

put the above lines in lets say test.c
===========================================

TARGETNAME=test
TARGETPATH=obj
TARGETTYPE=PROGRAM

SOURCES=test.c


UMTYPE=console
UMBASE=0x00400000
UMENTRY=main
put this is sources file (no extension just plain sources should be the name
and the entries after = are case sensitive MAIn , Main etc wont work just plain lower case main will work
=================================================

copy paste one of the makefile (no extension just plain makefile is the name of the file)
it will contain this

#
# DO NOT EDIT THIS FILE!!!  Edit .\sources. if you want to add a new source
# file to this component.  This file merely indirects to the real make file
# that is shared by all the driver components of the Windows NT DDK
#

!INCLUDE $(NTMAKEENV)\makefile.def

============================================

open the cmd prompt and type build

your hello world exe should be ready




now that i got rid of hello world lets try make one hello gui message box

here is the sources file

TARGETNAME=test
TARGETPATH=obj
TARGETTYPE=PROGRAM

SOURCES=test.c


UMTYPE=windows
UMBASE=0x00400000
UMENTRY=winmain


note windows and winmain in lower case WinMain wont work :)

src for gui


#include <windows.h>


int APIENTRY WinMain (HINSTANCE hInst,
                      HINSTANCE hPrevInstance,
                      LPSTR lpCmdLine,        
                      int nCmdShow )          
{

MessageBox(NULL,"Hello DDK Gui","Neat Gui MsgBox",MB_OK);
return 0;
}


type build and there is your exe :)

now lets use some third party code

i took winprog (forgers source code menu_one.c


TARGETNAME=test
TARGETPATH=obj
TARGETTYPE=PROGRAM

SOURCES=menu_one.c \
menu_one.rc



UMTYPE=windows
UMBASE=0x00400000
UMENTRY=winmain


type in build and it compiles with rc :)

hopefully this entry saves some eccentrics time reinventing these wheel again

cheers












Blog Comments
sebastianapelt Posted: Thursday, July 12 2007 04:37.17 CDT
lol nice job that you found out how to do this! some time last year i stumbled over quite the same problem (as far as i remember)..  but i gave up after some HOURS(!)... >_<

i'll try what you're writing here :) thx for sharing this info!


anonymouse Posted: Friday, July 13 2007 10:43.45 CDT
sebastianapelt i'll try what you're writing here :) thx for sharing this info!


so since you wish to give me company in eccentrics hall of fame ill provide you with some more eccentric tricks :)

this time its how to build a dll and app that calls the dll :) using DDK

here's how you do it

dlls source code


#include "precomp.h"
#pragma hdrstop

//Globals
HINSTANCE DLLModuleHandle;



BOOL APIENTRY DllMain(HINSTANCE aHandle, DWORD  aReason, LPVOID aReserved)
{
switch (aReason)
{
case DLL_PROCESS_ATTACH:
       DLLModuleHandle = aHandle;
       DisableThreadLibraryCalls(DLLModuleHandle);  
break;

     case DLL_THREAD_ATTACH:
     case DLL_THREAD_DETACH:
     case DLL_PROCESS_DETACH:
     break;
   }
return TRUE;
}

UINT AddTwoNum(UINT a,UINT b)
{
return a+b;
}

UINT SubTwoNum(UINT a,UINT b)
{
return a-b;
}

UINT MulTwoNum(UINT a,UINT b)
{
return a*b;
}


if you notice you will see a weird precomp.h and no other includes let me come to it later all else are standard

to build a dll there is a need for .def file the contents of .def file are here


LIBRARY TestDll

EXPORTS
AddTwoNum
SubTwoNum
MulTwoNum


here is the contents of testdll.h


#include <windows.h>
#include <stdio.h>
__declspec(dllexport) UINT  AddTwoNum(UINT a,UINT b);
__declspec(dllexport) UINT  SubTwoNum(UINT a,UINT b);
__declspec(dllexport) UINT  MulTwoNum(UINT a,UINT b);


now what does precomp.h hold ?
simple it refernaces the testdll.h


#include "TestDll.h"


now the mandatory sources file content


TARGETNAME=TestDll
TARGETTYPE=DYNLINK
DLLENTRY=_DllMainCRTStartup
USE_MSVCRT=1

SAMPLE_COMMON_DIR=D:\DDKTests

TARGETPATH=$(SAMPLE_COMMON_DIR)


SOURCES= TestDll.c

TARGETLIBS= \
       $(SDK_LIB_PATH)\user32.lib \
       $(SDK_LIB_PATH)\kernel32.lib \


UMTYPE=windows

PRECOMPILED_INCLUDE=precomp.h
PRECOMPILED_PCH=precomp.pch
PRECOMPILED_OBJ=precomp.obj


so why a weird precomp.h ?

if you notice the sources file you will see

SAMPLE_COMMON_DIR=D:\DDKTests

TARGETPATH=$(SAMPLE_COMMON_DIR)

the precomp.h will first get precompiled and make a testdll.lib which is needed for our testapp.exe

you also need that copypasted makefile in this directory

the total contents of the directory


D:\DDKTests\TestDll>dir /b
Testdll.h
makefile
precomp.h
sources
TestDll.c
TestDll.def

D:\DDKTests\TestDll>

now lets create a Test app

code for testapp.c

[code]
#include "precomp.h"
#pragma hdrstop


int __cdecl main (void)
{

int result,a,b;
a = 10;
b = 5;

printf("\nCompiling UserModeDll with DDk\n\nAnd Calling Functions From Dll\n\n");
printf("Following three calls are done from TestDll\n\n");

result = AddTwoNum(a,b);
printf("Addition of Two numbers       %d, %d = %d\n",a,b,result);

result = SubTwoNum(a,b);
printf("Subtraction of Two numbers    %d, %d = %d\n",a,b,result);
result = MulTwoNum(a,b);

printf("Multiplication of Two numbers %d, %d = %d\n",a,b,result);
printf("done\n");

return 0;
}


this too has just one precomp.h
which simply referances the testdll.h


#include "TestDll.h"


copy paste the testdll.h from testdll directory

the mandatory sources file for testapp.c


TARGETNAME=TestApp
TARGETTYPE=PROGRAM

SAMPLE_COMMON_DIR=D:\DDKTests

TARGETPATH=$(SAMPLE_COMMON_DIR)


UMENTRY=main

SOURCES=TestApp.c
        
TARGETLIBS=D:\DDKTests\i386\TestDll.lib

UMTYPE=console

PRECOMPILED_INCLUDE=precomp.h
PRECOMPILED_PCH=precomp.pch
PRECOMPILED_OBJ=precomp.obj



now you can see the targetpath and targetlib

TARGETLIBS=D:\DDKTests\i386\TestDll.lib

the common directory always has a diectory named i386 and we are refernacing the still to be build testdll.lib in the sources that will become available when the dll is built

the directory of testapp is like this


D:\DDKTests\TestApp>dir /b
makefile
sources
TestApp.c
precomp.h
Testdll.h

D:\DDKTests\TestApp>



now we get to the root directory and create a dirs file (plain dirs no extension

why do you need it coz it contains the directories that are going to be buit

contents of dirs file


DIRS= \
     TestDll \
     TestApp \


see a complete tree before we build this


D:\DDKTests>tree /f
Folder PATH listing
D:.
��   dirs
��
��������TestApp
��       makefile
��       sources
��       TestApp.c
��       precomp.h
��       Testdll.h
��
��������TestDll
        Testdll.h
        makefile
        precomp.h
        sources
        TestDll.c
        TestDll.def


D:\DDKTests>


we now just type in build :) on the root directory



D:\DDKTests>build
BUILD: Adding /Y to COPYCMD so xcopy ops won't hang.
BUILD: Object root set to: ==> objfre_w2K_x86
BUILD: Compile and Link for i386
BUILD: Loading D:\WINDDK\3790~1.183\build.dat...
BUILD: Computing Include file dependencies:
BUILD: Examining d:\ddktests directory tree for files to
    d:\ddktests\testdll - 2 source files (39 lines)
    d:\ddktests\testapp - 2 source files (27 lines)
Total of 4 source files (66 lines) to compile in 2 direct

BUILD: Compiling (NoSync) d:\ddktests\testdll directory
Precompiling - precomp.h for i386
Compiling - testdll.c for i386
Building Library - .lib for i386
BUILD: Compiling (NoSync) d:\ddktests\testapp directory
Precompiling - precomp.h for i386
Compiling - testapp.c for i386
BUILD: Linking d:\ddktests\testdll directory
Linking Executable - testdll\i386\testdll.dll for i386
BUILD: Linking d:\ddktests\testapp directory
Linking Executable - testapp\i386\testapp.exe for i386
BUILD: Done

    6 files compiled -    13 LPS
    1 library built
    2 executables built

D:\DDKTests>
[code]

lets check the tree what it built

[code]

D:\DDKTests>tree /f
Folder PATH listing
Volume serial number is 71FAE346 191A:1EDE
D:.
��   dirs
��   buildfre_w2K_x86.log
��
��������TestApp
��   ��   makefile
��   ��   sources
��   ��   TestApp.c
��   ��   precomp.h
��   ��   Testdll.h
��   ��
��   ��������objfre_w2K_x86
��       ��   _objects.mac
��       ��
��       ��������i386
��               precomp.pch
��               precomp.obj
��               testapp.obj
��
��������TestDll
��   ��   Testdll.h
��   ��   makefile
��   ��   precomp.h
��   ��   sources
��   ��   TestDll.c
��   ��   TestDll.def
��   ��
��   ��������objfre_w2K_x86
��       ��   _objects.mac
��       ��
��       ��������i386
��               precomp.pch
��               precomp.obj
��               testdll.obj
��
��������i386
        TestDll.lib
        TestDll.exp
        TestDll.dll
        TestDll.pdb
        TestApp.exe
        TestApp.pdb


D:\DDKTests>
[code]

lets try running the app and see if it really works ?

[code]

D:\DDKTests\i386>TestApp.exe

Compiling UserModeDll with DDk

And Calling Functions From Dll

Following three calls are done from TestDll

Addition of Two numbers       10, 5 = 15
Subtraction of Two numbers    10, 5 = 5
Multiplication of Two numbers 10, 5 = 50
done

D:\DDKTests\i386>


ok look like its a success on first sight

lets try disassembling it


01001D15 >MOV EDI,EDI
01001D17  PUSH ESI
01001D18  PUSH EDI           ; /format
01001D19  PUSH TestApp.??_C@_0EC@LBDINKF@?6Compili>; |/format = " Compiling UserModeDll with DDk And Calling Functions From Dll"
01001D1E  CALL TestApp.printf             ; |\printf
01001D23  MOV DWORD PTR SS:[ESP],TestApp.??_C@_0CO>; |ASCII "Following three calls are done from TestDll

"
01001D2A  CALL TestApp.printf        ; \printf
01001D2F  POP ECX
01001D30  PUSH 5
01001D32  POP EDI
01001D33  PUSH EDI
01001D34  PUSH 0A
01001D36  POP ESI
01001D37  PUSH ESI
01001D38  CALL TestApp._AddTwoNum@8;JMP to TestDll.AddTwoNum
01001D3D  PUSH EAX                                 ; /<%d>
01001D3E  PUSH EDI                                 ; |<%d>
01001D3F  PUSH ESI                                 ; |<%d>
01001D40  PUSH TestApp.??_C@_0CL@HHFCGPC@Addition?>; |format = "Addition of Two numbers       %d, %d = %d
"
01001D45  CALL TestApp.printf                      ; \printf

010011F8=TestApp.??_C@_0EC@LBDINKF@?6Compiling?5UserModeDll?5with?5DDk?6@ (ASCII 0A,"Compiling ")
testapp.c:12.  printf("\nCompiling UserModeDll with DDk\n\nAnd Calling Functions From Dll\n\n");

looks like name mangling has been done
i tried extern "C" before __declspec but i find ddk is complaining have to find out how to remove this mangling crap

following the dll function
testdll.c:28.  return a+b;


46A010AD >MOV EDI,EDI                    ; {
46A010AF  PUSH EBP                       ; {
46A010B0  MOV EBP,ESP
46A010B2  MOV EAX,DWORD PTR SS:[EBP+C]   ; return a+b;
46A010B5  MOV ECX,DWORD PTR SS:[EBP+8]
46A010B8  ADD EAX,ECX
46A010BA  POP EBP                        ; }
46A010BB  RETN 8






ok thats all for now happy ddk'ing



anonymouse Posted: Friday, July 13 2007 11:56.48 CDT
i zipped up all the project directories to my repository

if any one wishes to play with this

https://www.openrce.org/repositories/users/anonymouse/DDKTests.zip

to build all sample type build in your build environment

here is a tree structure before and after building

[code]
Folder PATH listing
D:.
|   dirs
|   beforebuild.txt
|  
+---TestApp
|       makefile
|       sources
|       TestApp.c
|       precomp.h
|       Testdll.h
|      
+---TestDll
|       Testdll.h
|       makefile
|       precomp.h
|       sources
|       TestDll.c
|       TestDll.def
|      
+---TestConHello
|       sources
|       makefile
|       testconhello.c
|      
\---TestGuiHello
        testgui.c
        sources
        makefile

after typing build
        
Folder PATH listing
D:.
|   dirs
|   beforebuild.txt
|   buildchk_w2K_x86.log
|  
+---TestApp
|   |   makefile
|   |   sources
|   |   TestApp.c
|   |   precomp.h
|   |   Testdll.h
|   |  
|   \---objchk_w2K_x86
|       |   _objects.mac
|       |  
|       \---i386
|               precomp.pch
|               precomp.obj
|               testapp.obj
|              
+---TestDll
|   |   Testdll.h
|   |   makefile
|   |   precomp.h
|   |   sources
|   |   TestDll.c
|   |   TestDll.def
|   |  
|   \---objchk_w2K_x86
|       |   _objects.mac
|       |  
|       \---i386
|               precomp.pch
|               precomp.obj
|               testdll.obj
|              
+---TestConHello
|   |   sources
|   |   makefile
|   |   testconhello.c
|   |  
|   \---objchk_w2k_x86
|       |   _objects.mac
|       |  
|       \---i386
|               testconhello.obj
|              
+---TestGuiHello
|   |   testgui.c
|   |   sources
|   |   makefile
|   |  
|   \---objchk_w2k_x86
|       |   _objects.mac
|       |  
|       \---i386
|               testgui.obj
|              
\---i386
        TestDll.lib
        TestDll.exp
        TestDll.dll
        TestDll.pdb
        TestApp.exe
        TestApp.pdb
        testconhello.exe
        testconhello.pdb
        testgui.exe
        testgui.pdb

cheers
        


MohammadHosein Posted: Friday, July 13 2007 14:15.34 CDT
good job anon , thanks for sharing

Assarbad Posted: Wednesday, March 12 2008 19:54.50 CDT
Hey, "one assarbad" here.

You could have simply asked in a comment to my blog post. Yes you have to turn it off, and I explained why. It is actually a real bug and starting up IDA and looking into the involved files will quickly reveal this, as I wrote in my blog.

Also you didn't search very good, since there is DDKWizard (ddkwizard.assarbad.net). It allows you to create DDKBUILD projects with Visual Studio .NET through 2008. And that's where the next topic comes in: DDKBUILD (.bat or .cmd, also available from my DDKWizard page) is much more convenient to build DDK/WDK projects. And yes, DDKBUILD works completely independent of Visual Studio, so DDKWizard is just an extra goody you can get if you like, but not needed at all.

Also DDKWizard contains a project template for Win32 DLLs and for console programs. And that's where we come to the advantage of using the DDK/WDK for compiling usermode (Win32) code. The advantage is, that the files involved (and mainly msvcrt.dll) are now system DLLs. First of all all systems starting with XP have it and furthermore the most current SPs for Windows 2000 also have it. This is where your printf() and friends come from. Looking into the templates you will find lines in the SOURCES file(s) such as:

USE_MSVCRT=1
USE_STL=1
STL_VER=70

These are relevant for what you want to do. If you want to find out more about that stuff, I suggest you have a look into the bin/ folder of your DDK/WDK and check out the file makefile.new to get a hint as to which options are available and how to use them.

To quote myself from the blog:

"However, the bufferoverflow.lib in the W2K directory does not contain any implementation (verified by disassembling) of NtProcessStartupForGS (the ones for WXP and WNET do!), while i386mk.inc still insists to use this function as the entry point to the executable" ... so it's not just an opinion that it doesn't work. You have to either offer your own implementation of this function or circumvent it. The only thing I didn't understand from your post is, that you seem to want to create a Win32, not a native, application but you seem to compile it as native. There is no other explanation why it would even look for NtProcessStartupForGS() in a Win32 application.

Assarbad Posted: Wednesday, March 12 2008 20:02.05 CDT
Oh, btw. I forgot another advantage of the DDK/WDK: PREfast. Just google it or use whatever search engine you like. It's a very useful and free tool for static analysis.

anonymouse Posted: Tuesday, March 18 2008 13:24.48 CDT
assarbad wrote You could have simply asked in a comment to my blog post

laziness :) releutance to create a pseudonym and register :)
reluctance to create a throwaway email address for the purpose of registering :) releuctance to remember a new password just for posting one time comment :)
releuctance to post a may be valubale question that i could brag about under anonymous accounts :) you want some more reason ?? i can still list quiet a few of them


yep saw the ddkwizard but i wasnt much interested in automatic solutions (i havent even tried hollistics original ddkbuild yet ) all i was interested in was how to do it myself like i posted you could term it  an eccentric's perspective

assarbad wrote
The only thing I didn't understand from your post is, that you seem to want to create a Win32, not a native, application but you seem to compile it as native.


can you explain further if possible where i compile it as native the source is the post and the compiling method is in the post

how did you conclude that i was compiling it as native

all i was trying to do was simply cl balh.c as simple as that with cl in wdk

thanks for noticing the post and many thanks for commenting back i appreciate that very much




Assarbad Posted: Tuesday, October 28 2008 16:45.19 CDT
how did you conclude that i was compiling it as native
Why else would the linker complain about "NtProcessStartup"?

BTW: it would really help to get notifications about replies ...
Also, it isn't necessary to register in my blog to comment and disposable email addresses are available through spamgourmet.com and you create them whenever you enter them. There's no "create email address" per-se ;)

NeOXQuiCk Posted: Tuesday, October 28 2008 19:18.11 CDT
thx nice contribution..



Add New Comment
Comment:









There are 31,316 total registered users.


Recently Created Topics
[help] Unpacking VMP...
Mar/12
Reverse Engineering ...
Jul/06
hi!
Jul/01
let 'IDAPython' impo...
Sep/24
set 'IDAPython' as t...
Sep/24
GuessType return une...
Sep/20
About retrieving the...
Sep/07
How to find specific...
Aug/15
How to get data depe...
Jul/07
Identify RVA data in...
May/06


Recent Forum Posts
Finding the procedur...
rolEYder
Question about debbu...
rolEYder
Identify RVA data in...
sohlow
let 'IDAPython' impo...
sohlow
How to find specific...
hackgreti
Problem with ollydbg
sh3dow
How can I write olly...
sh3dow
New LoadMAP plugin v...
mefisto...
Intel pin in loaded ...
djnemo
OOP_RE tool available?
Bl4ckm4n


Recent Blog Entries
halsten
Mar/14
Breaking IonCUBE VM

oleavr
Oct/24
Anatomy of a code tracer

hasherezade
Sep/24
IAT Patcher - new tool for ...

oleavr
Aug/27
CryptoShark: code tracer ba...

oleavr
Jun/25
Build a debugger in 5 minutes

More ...


Recent Blog Comments
nieo on:
Mar/22
IAT Patcher - new tool for ...

djnemo on:
Nov/17
Kernel debugger vs user mod...

acel on:
Nov/14
Kernel debugger vs user mod...

pedram on:
Dec/21
frida.github.io: scriptable...

capadleman on:
Jun/19
Using NtCreateThreadEx for ...

More ...


Imagery
SoySauce Blueprint
Jun 6, 2008

[+] expand

View Gallery (11) / Submit