scdbg shellcode analysis

What is scdbg? top

scdbg is an open source, multi-platform, shellcode analysis application that runs shellcode through a virtual machine that emulates a 32bit processor, memory, and basic Windows API environment. scdbg uses the libemu library to provide this environment. Builds of scdbg exist for both Windows and Unix users.

Scdbg homepage is:

Versions of scdbg are available for both *nix and Windows machines. The Windows version is the current development branch and includes many features not found in the older gcc builds.

At the time of writing, this includes support for 246 opcodes, 15 Dlls, and 242 API hooks. You can view these stats along with exactly which API are supported by using the -hooks command line option.

To see just the dll list use the -dllmap option.

        kernel32 Dll mapped at 7c800000 - 7c8f6000  Version: 5.1.2600.5781
        ntdll    Dll mapped at 7c900000 - 7c9b2000  Version: 5.1.2600.5755
        ws2_32   Dll mapped at 71ab0000 - 71ac7000  Version: 5.1.2600.5512
        iphlpapi Dll mapped at 76d60000 - 76d79000  Version: 5.1.2600.5512
        user32   Dll mapped at 7e410000 - 7e4a1000  Version: 5.1.2600.5512
        shell32  Dll mapped at 7c9c0000 - 7d1d7000  Version: 6.0.2900.6018
        msvcrt   Dll mapped at 77c10000 - 77c68000  Version: 7.0.2600.5512
        urlmon   Dll mapped at 78130000 - 78258000  Version: 7.0.6000.17096
        wininet  Dll mapped at 3d930000 - 3da01000  Version: 7.0.6000.17093
        shlwapi  Dll mapped at 77f60000 - 77fd6000  Version: 6.0.2900.5912
        advapi32 Dll mapped at 77dd0000 - 77e6b000  Version: 5.1.2600.5755
        shdocvw  Dll mapped at 7e290000 - 7e401000  Version: 6.0.2900.5512
        psapi    Dll mapped at 76bf0000 - 76bfb000  Version: 5.1.2600.5512
What can scdbg do? top

As scdbg runs shellcode, it will print out the API log of what the shellcode is attempting to do. By default, shellcode is not allowed to create files, or access the network. To try to keep the shellcode running smooth, many API are spoofed with fake return values.

	D:\>scdbg -f ./sc/
	Loaded 21b bytes from file ./sc/
	Initialization Complete..
	Max Steps: 2000000
	Using base offset: 0x401000
	4010a3  GetTempPathA(len=ff, buf=40121b) = 8
	4010c8  _lcreate(d:\temp\.com)
	4010de  _lwrite(h=4, buf=40111b)
	4010e8  _lclose(h=4)
	4010f8  WinExec(d:\temp\.com)
	401104  Sleep(0x7d0)
	401112  DeleteFileA(d:\temp\.com)
	40111b  ExitProcess(0)
	Stepcount 1616895

If the -i interactive mode is enabled, then shellcode will be allowed to access the network, and gain controlled ability to read/write files to disk. The file read/write ability is completely controlled by scdbg and influenced through several command line options to be discussed latter in the File System Access section.

	D:\>scdbg -i -f ./sc/
	Loaded 21b bytes from file ./sc/
	Initialization Complete..
	Interactive Hooks enabled
	Max Steps: 2000000
	Using base offset: 0x401000
	4010a3  GetTempPathA(len=ff, buf=40121b) = 8
	4010c8  _lcreate(d:\temp\.com)
	        Interactive mode local file: ./sc/dropz.drop_0
	4010de  _lwrite(h=4fd2d0, buf=40111b)
	4010e8  _lclose(h=4fd2d0)
	4010f8  WinExec(d:\temp\.com)
	401104  Sleep(0x7d0)
	401112  DeleteFileA(d:\temp\.com)
	40111b  ExitProcess(0)
	Stepcount 1616895

scdbg has support for:

  • file format exploits which extract executables from parent files and drop them to disk. In scenarios such as this, you use the -f option to load the shellcode, and the -fopen option to give it access to the parent document.

  • multistage shellcodes that load the second stage either via network sockets or from a parent exploit document.

  • process injection shellcode. New threads (including remote) will be run in the same environment seamlessly for streamlined analysis.

  • assembler level analysis of the shellcode
  • debug shell with breakpoints, single stepping and memory analysis tools
  • ability to redirect net socket connections to server of your choice
  • ability to log access to raw dll memory and detect API memory patching
  • creating memory dumps of decoded shellcode
  • running analysis reports of shellcode run and memory access
  • locating shellcode start offsets
  • hex and disasm dumps of shellcode files
  • ability to dynamically patch shellcode just before execution
  • support for shellcode which uses structured exception handling
  • can detect and run jmp api+5 type hooks.
  • can handle memory allocs and shellcode which runs from allocs

Help Videos top

Several help videos are available:

Loading shellcode into scdbg: top

The primary way to load shellcode into scdbg is with the -f option. This option takes a file path as an argument. For Linux users, this must be a binary file of the shellcode.

For Windows users, this can now also be a %u, %x, \x, or hex blob text representations of the shellcode which will be auto converted to binary before execution. The converters are pretty basic and while they will ignore new lines, tabs, quotes, and plus signs, they can not parse javascript variable assignments and the like. If in doubt, manually convert it to binary first, or use -conv [path] option to dump the converted data to disk as a binary file before running.

For testing purposes, you can also load shellcode into memory using the patching functionality, or raw file loading capabilities along with the -nofile option. See the Patching section for more details.

GUI Launcher: top

Perhaps the easiest way to run scdbg is to use gui_launcher.exe which is a graphical user interface that presents the user with visual options to launch the scdbg console application. The interface has checkboxes for most of the commonly used options, as well as the ability to graphically browse for the shellcode file, or launch several options from a right click menu.

Shellcode files can also be loaded by dragging and dropping them into the upper textbox.

If an option is not broken out to an individual checkbox, it is still available through the Manual args text box which will be appended to the built up command line. The last command line can also be copied to the clipboard for manual debugging.

The gui application can also create a file association so that .sc files open automatically with it when they are double clicked. This is a very handy way to load shellcode files and gives them a slick icon to boot.

Finding Shellcode Start Offset: top

Sometimes you dont know where the shellcode starts, usually because there is a ROP gadget on the front of the shellcode. In these cases the best place to start is with the -findsc mode. Findsc option will try to start execution at each offset in the file, and see how many steps it can execute without an error. If it makes it to an API address, then it will also abort and assume a successful run.

If there is only possible start offset found (or if the -auto flag is used), it will go ahead and auto execute the shellcode from that point for a full report. If multiple possible start offsets are found, it will list them sorted by step count for you to select. For Windows users, a percent complete will be displayed to show progress.
	scdbg -f -findsc
	Loaded 651 bytes from file
	Testing 1617 offsets  |  Percent Complete: 99%  |  Completed in 484 ms
	0) offset=0x4af        steps=MAX    final_eip=7c86250d   WinExec
	1) offset=0x4b5        steps=MAX    final_eip=40150b
	2) offset=0x4b8        steps=MAX    final_eip=401503
	3) offset=0x4ba        steps=MAX    final_eip=401505
If execution reachs an API, it will be listed and moved to the top of the list. To select which start offset you would like to try, you enter the index listed not the actual offset (easier). If you just hit return, it will default to index 0.

If there are to many possible start offsets, you can also increase the minimum logging threshold through the use of the -min option.

Another technique to locate the start offset, is to use -dump to display a hex dump of the file. Nops, Calls, and JMPs will be highlighted in yellow. You can then use -disasm and -foff to get disasm listing of parts of the file. or use -foff to start execution where ever you want.

The older gcc builds also support the -getpc command which uses a different internal mechanism built into libemu itself.

Memory Dumps top

It is common for shellcode to decode itself in memory. In order to obtain a decoded copy of the shellcode after execution, you can use the -d dump option.

If this mode is specified, it will scan memory after execution and compare it to the buffer that was initially loaded in. If changes are detected, it will dump memory to disk in the shellcodes parent directory.

If any new memory allocations were created during runtime, they too will be dumped to disk and named by base offset.

You can also create memory dumps and view hexdumps of memory at anytime during execution from the debug shell.

IDA Integrationtop

Scdbg has support for syncing an IDA disassembly on breakpoint and single step events. Comments can also be added to IDA from the debug shell by pressing the semi colon key ;

In order to utilize this feature, you will need:
  • IDASrvr plugin must be installed
  • Shellcode was last disassembly opened.
  • idb base offset can be either 0 or match scdbg base
You can specify this mode at startup by using /ida on the command line, or from the debug shell type .idasync to connect

IDASrvr is open source and hosted on github. You can download the latest binary here:

Verbosity Levels top

scdbg supports 4 different verbosity levels to the output. By default verbosity = 0 and only initilization messages, API log output and errors will be displayed. Verbosity is increased by using the -v flag multiple times or by directly specifying it such as -vv, -vvv. Verbosity level table is below:
	none (v=0) = initilization messages, API log output and errors
	-v   (v=1) = 0 + assembler output and step count 
	-vv  (v=2) = 1 + register output 
	-vvv (v=3) = 2 + enters interactive debug shell and single step mode
	-vvvv(v=4) = 3 + stack dump on every step
Once you enter the debug shell, you can manually re-specify the verbosity again using the v command. So if you wanted to continue execution after a breakpoint with asm listing showing you could enter the debug shell commands v 1 and then r for run. (You can also slow down execution to keep the asm coming at a readable pace by setting a t 3 timeout interval). The debug shell g (go) command will automatically set v=0 and r

Initial register values top

Most shellcode is designed to be initial register value independant.

In an effort to avoid emulation, some require specific values at startup. One variant in particular use a register already pointing to the start of the shellcode buffer in order to avoid having to use get_pc code which AV has strong detections for.

You can set initial values of registers from the command line. using hex, decimal or keyword values. eg: -eax 0xdeadBeef or -ebx 12345 or -ecx base.

Esp and EBP can not be set in this manner. The base keyword uses the shellcodes base offset. If you modify the shellcodes base offset with the -o switch, it must be specified in teh command line before the register switch is set.

If you want to set all general registers to the same default value you can use -reg [value] switch. By default all general registers are set to 0.

ordinal lookups top

GetProcAddress does support ordinal lookups.

		4012f9  GetProcAddress(kernel32.0x245) - LoadLibraryA by ordinal
		401691  LoadLibraryA(kernel32)
		4012f9  GetProcAddress(kernel32.0x50) - CreateFileA by ordinal
		4012f9  GetProcAddress(kernel32.0x391) - WriteFile by ordinal
		4012f9  GetProcAddress(kernel32.0x2a7) - ReadFile by ordinal
		4012f9  GetProcAddress(kernel32.0x15c) - GetFileSize by ordinal
		4012f9  GetProcAddress(kernel32.0x32) - CloseHandle by ordinal
		4012f9  GetProcAddress(kernel32.0x385) - WinExec by ordinal
		4012f9  GetProcAddress(kernel32.0x1cc) - GetTempPathA by ordinal
		4012f9  GetProcAddress(kernel32.0x30a) - SetFilePointer by ordinal
		4012f9  GetProcAddress(kernel32.0x10a) - GetCommandLineA by ordinal
		4012f9  GetProcAddress(kernel32.0xb7) - ExitProcess by ordinal
		401691  LoadLibraryA(shell32)
		4012f9  GetProcAddress(shell32.0x167) - ShellExecuteA by ordinal
		401709  GetCommandLineA() = 2531d0
		40142e  GetTempPath(len=104, buf=12f858) = 8

-api mode top

The -api mode option will scan the main code body and any allocs just before termination looking for a continuous block of api pointers. If it can locate the API table, it will dump it so you can see what api the shellcode loads and what the relative offsets are.

This is useful if the shellcode is crashing somewhere after lookups are done but before it completes execution.

	Scanning main code body for api table...
	Scanning stack for api table start=12fdbc sz=c
	Scanning runtime memory alloc 0  base=60000, sz=28
	        Found Api table at: 60000
	        table is eax based
	                [x + 0] = GlobalAlloc
	                [x + 4] = LoadLibraryA
	                [x + 8] = URLDownloadToCacheFileA
	                [x + 12] = keybd_event

Process Injection Shellcode: top

Process injection and CreateThread shellcode is handled all at once seamlessly.

	401051  GetEnvironmentVariableA(name=ProgramFiles, buf=12fcf4, size=fc)  
	4010bb  CreateProcessA( C:\Program Files\Internet Explorer\iexplore.exe,  ) = 0x1269
	4010dd  VirtualAllocEx(pid=1269, base=0 , sz=644) = 600000
	4010f8  WriteProcessMemory(pid=1269, base=600000 , buf=40110f, sz=644, written=0)
	40110a  CreateRemoteThread(pid=1269, addr=600000 , arg=0, flags=0, *id=0)
	        Transferring execution to threadstart...
	600030  VirtualProtect(adr=600000, sz=1000, flags=40)
	60027f  LoadLibraryA(ws2_32.dll)
	6002ab  LoadLibraryA(wininet.dll)
	60027f  LoadLibraryA(ws2_32.dll)
	6002ab  LoadLibraryA(wininet.dll)
	60027f  LoadLibraryA(ws2_32.dll)
	6002ab  LoadLibraryA(wininet.dll)
	60027f  LoadLibraryA(ws2_32.dll)
	6002ab  LoadLibraryA(wininet.dll)
	6002e8  WSAStartup(101)
	600302  CreateThread(600536, 60000b) = 1
	        Transferring execution to threadstart...
	600547  socket(2, 1, 6) = 41
	600567  bind(h=41, port:5746, sz=10) = 15
	600575  listen(h=41) = 21
	600583  accept(h=41, sa=21, len=21) = 68
	6005a1  recv(h=68, buf=12fc70, len=4, fl=0)
	600644  ExitThread(0)

File Format Exploits: top

File format exploits such as PDF, Word, Excel that extract executables or second stage shellcode from the parent exploit document can be easily analyzed by scdbg. These shellcode typically call GetFileSize with incrementing file handles trying to find an open handle to the parent document that the exploited application opened to load the document.

In scdbg, this handle can be provided by using the -fopen [path] option along with -i for interactive hooks. This functionality is available in both the Linux and Windows builds.

		$ ./sctest -f -fopen bad.pdf -i
		fopen(bad.pdf) = 4d565c
		Loaded 312 bytes from file
		Initialization Complete..
		Interactive Hooks enabled
		401083  GetFileSize(4) = 2031b
		401112  GlobalAlloc(sz=2031b) = 60000
		401118  SetFilePointer(hFile=4, dist=0, FILE_BEGIN)
		401132  ReadFile(hFile=4, buf=60000, numBytes=2031b)
		401147  CreateFile(x.exe)
		        Interactive mode local file: /tmp/WHhUmhtM
		401158  WriteFile()
		401176  WinExec(x.exe)

In the above example, the newly created file /tmp/WHhUmhtM will now contain a fully decoded exe that the emulated shellcode safely extracted from the parent document.

File System Access: top

By default, no file system access is allowed to the shellcode, and spoofed file handles and data are returned by the emulated API.

Under limited circumstances, actual file system is allowed when specified by the command line switches.

In -i interactive mode the shellcode is allowed to write files to disk, however scdbg controls the location and file names. For Linux versions, this will always be in the temp directory under random file names.

For newer Windows versions, they will be named sample_x.drop in the shellcodes home directory. The current directory can be overridden with the -temp command line option.

Similarly, memory dumps taken with the -d option will be saved to the shellcode parent directory.

Shellcode can also access files you specify with the -fopen option. In these situations it will be provided with a read only handle to the file you specify. This is used for file format shellcode which want to read in data from the parent file.

The -cfo option (CreateFileOverride) can also provide access similar to -fopen.

Create File Override option -cfo top

The -cfo option is used for shellcodes which do a download, then open the downloaded file to decode it. In these scenarios, you can use -cfo [path] to have scdbg direct the first CreateFile call to open the file you specify. Subsequent CreateFile calls (if -i is enabled) will be used to drop the decoded file to disk. its a bit of a hack but works and is useful.

    scdbg -f -fopen Zoll.exe_ -i -cfo -norw
	fopen(Zoll.exe_) = 7c4
	Loaded 410 bytes from file
	Initialization Complete..
	Interactive Hooks enabled
	Max Steps: 2000000
	Using base offset: 0x401000

	401056  LoadLibraryA(User32)
	401075  LoadLibraryA(urlmon)
	401094  LoadLibraryA(shell32)
	4010c7  MultiByteToWideChar(
	4010ed  URLDownloadToCacheFileW(, buf=4014c2)
	40110e  CreateFileW(c:\URLCacheTmpPath.exe) = 7c4
	401120  GetFileSize(7c4, 0) = 8800
	401158  CreateFileW(c:\URLCbcheTmpPath.exe) = 7a8
	        Interactive mode local file happy.drop_0
	40117d  SetFilePointer(hFile=7c4, dist=0, 0, FILE_BEGIN) = 0
	4011f7  CloseHandle(7c4)
	401200  CloseHandle(7a8)
	4012c9  WinExec(cmd.exe /c copy /B "c\RCcemPt.x" /B %temp%\svchost.exe /y && start %temp%\svchost.exe)
	4012ce  ExitProcess(0)
MemMonitor top

scdbg supports a memory monitor that will watch for access to DLL memory regions as well as to the PEB. it can automatically detect read/writes to these regions and report on it. This allows us to easily find API patching, and which module list is used from the PEB. Memory monitor -mm is enabled automatically for -r report mode, as well as a more verbose and immediate output available through the -mdll option as shown below.

Patching: top

There are several times during testing, development, and analysis where the need for patching code into the emulated environment became necessary. There are now several mechanisms in place, all of which can be used to write test code to memory and can patch shellcode loaded with -f just before execution.

The first patching mechanism implemented was the -patch [file] command. This option uses a specially constructed binary patch file format that can hold multiple patches per file. Patch files are generated with the "Generate Patch" command available within gui_launcher More menu. A blog post with example file can be downloaded here:

Another way to load raw data into emu memory is with the -raw 0xBase-fpath. This command will load the file specified by fpath into memory directly as is at 0xBase address.

ex: -raw 0x403000-c:\test.bin

This command was implemented as a lazy way to load dll memory dumps for testing with ROP exploits. It is not PE aware. (-raw is also handy to use with the -llo Load Library Override option)

The last two commands are -wint 0xBase-0xVal and -wstr 0xBase-Str . In some examples you may see them aliased as -spoke and -poke. -wint is short for write int, and is designed to write an integer value into memory at 0xBase. -wstr is short for write string, is can write a string into memory at 0xBase address.

-wstr is capable of writing ascii, or binary data into memory. ex: scdbg /wstr 0x401000-0x64A130000000060fa00731C026A13000000090 -vvv -nofile

SCMD Files: top

scdbg has special handleing of .scmd files. These files are a sort of scdbg script file that allow you to place each command line option on its own line in a text file, and also supports # style comments per line. An example scmd file is available here:

scmd files can also be launched by dragging and dropping them onto the scdbg icon.

Directory Mode: top

You can run scdbg across an entire directory of shellcode in a batch mode if you like. It will process all .sc files in the directory you specify with the -d [folder] command line. This mode will output one file per shellcode file it finds. You can also have all the results output to a single file with the (override) of the -r report option.

If you want report mode on each file use the (override of) the -v option (now meaning Verbose in this case) Directory mode also supports the -u unlimited steps command, but be careful this could cause hangs.

You can also run directory mode by dragging and dropping a folder onto the scdbg icon.

BreakPoints and Debug Shell: top

The debug shell is a basic interface that allows you pause shellcode execution, and enter manual commands to analyze instructions, registers, and memory. You can enter the debug shell at any time during execution by hitting CTRL-C

There are also several ways to enter the debug shell at specific times such as:

	  /ba hexnum            break above - breaks if eip > hexnum
	  /bp hexnum            set breakpoint on virtual address, file offset or api name
	  /bs int               break on step (shortcut for -las [int] -vvv)
	  /b0                   break if 00 00 add [eax],al
You can set up to 10 breakpoints with -bp. The other options all use the same internal mechanism and can only be used one at a time. -bp breakpoints can be managed in the debug shell using the .bl (bp list), .bc (bp clear), and b (bp set) commands. You can also have it automatically enter the debug shell if it encounters an error during execution with -e 3 which means error mode set verbosity to 3.

If you want to enter the debug shell right at the beginning of execution you can set verbosity to 3 with -vvv

The debug shell has a number of commands available. When in the debug shell, type ? to see a full listing of commands. The current list of commands is:
	dbg> ?
        ? - help, this help screen, h also works
        v - change verbosity (0-4)
        g - go - continue with v=0
        s - step, continues execution, ENTER also works
        c - reset step counter
        r - execute till return (v=0 recommended)
        u - unassembled address
        b - sets next free breakpoint (10 max)
        m - reset max step count (-1 = infinate)
        e - set eip
        w - dWord dump,(32bit ints) prompted for hex base addr and then size
        d - Dump Memory (hex dump) prompted for hex base addr and then size
        x - execute x steps (use with reset step count)
        t - set time delay (ms) for verbosity level 1/2
        k - show stack
        i - break at instruction (scans disasm for next string match)
        f - dereF registers (show any common api addresses in regs)
        j - show log of last 10 instructions executed
        o - step over
        ; - Set comment in IDA if .idasync active
        +/- - basic calculator to add or subtract 2 hex values
        .bl - list set breakpoints
        .bc - clear breakpoint
        .api - scan memory for api table
        .seh - shows current value at fs[0]
        .segs - show values of segment registers
        .reg - manually set register value
        .dllmap - show dll map
        .poke1 - write a single byte to memory
        .poke4 - write a 4 byte value to memory
        .lookup - get symbol for address
        .symbol - get address for symbol (special: peb,dllmap,fs0)
        .savemem - saves a memdump of specified range to file
        .idasync - connect IDASrvr plugin and sync view at step or break.
        q - quit
ROP shellcode: top

Many modern shellcodes will include ROP gadgets at the beginning of the shellcode. These usually just setup memory for the main shellcode that follows it to run. Since the main shellcode does not start at the beginning of the payload, you often have to locate the shellcode start offset. For help with this, see the Finding Shellcode Start Offset section of the manual.

scdbg does have some support for analyzing ROP shellcode chains. using -dllmap you can see the dlls (and version) that scdbg has built in support for. Note that only NTDLL and Kernel32 have the full opcodes included which ROP payloads often use. (Its not worth megabytes upon megabytes of distribution size for the others and even these two only have opcodes included for hook detectors and return address scanners)

A ROP shellcode can be executed using the -rop flag. You may have to load other dlls into memory using -raw. It was an interesting experiment to add this mode, but probably not of much use. In practice, just use -findsc to find the real shellcode start offset and your fine. If its truly a ROP only shellcode, it will take more work to use scdbg to analyze it than necessary.

More info is available on my blog here:

Signatures top

scdbg supports a basic signature engine. This is used for -r report mode. You can view the built in signatures through the -sigs option. The -disasm option can be added to show the disassembly of each signature.

Running as a web

A sample php script is available that will allow you to run scdbg as a web service. It is designed for the windows build, but could be modified to run the linux version as well. On windows, the easiest way to set it up is to use the WAMP server package. I would not recommend running it as a world accessible service.

The script can be found in the github repository in the /support/webservice folder.

Converting API logs to IDC scriptstop

A quick and dirty converter is available that can convert scdbg api logs into IDC scripts to add them as comments to the IDA disassembly. The comment will be added on the line after the call (the return address). This can be accessed by running gui_launcher and choosing API to IDC from the More menu.

Hook checks and RET scannerstop

Since scdbg does not use runtime hooking to intercept API calls, there are no embedded JMP instructions at API starts to be detected. There are however some shellcodes which do not try to detect hooks, and instead always run their own prolog and do a jmp api+5

Scdbg can detect and handle these shellcodes automatically:

	4010eb  GetTempPathA(len=100, buf=12e048) = 8
	        jmp CreateFileA+5 hook evasion code detected! trying to recover...
	40111f  CreateFileA(d:\temp\\scvhost.exe) = 4
	40113c  WriteFile(h=4, buf=401214, len=0, lpw=12e048, lap=0) = 1
	401142  CloseHandle(4)
	        jmp WinExec+5 hook evasion code detected! trying to recover...
	401186  WinExec(cmd.exe /c "%temp%\scvhost.exe")
Some shellcode will also scan dll memory for ret addresses to use to bypass some security software. scdbg also includes support for these types of shellcodes (they usually scan ntdll or kernel32 which both support this)

Complete command line options: top

This document is not a complete listing of all command line options. Many can be figured out just from the brief help shown from the applications -h help screen.

for a complete listing of command line options, run scdbg -h (or with no arguments) to get a dump of its compile date, and the options its supports. All command line switches can be run with either a - or a / prefix. ex: /h or -h

scdbg does not have version numbers, instead its compile date is shown on the help screen.

When in the debug shell, type ? to see a complete listing of commands the debug shell supports.

Credits top

	scdbg Developer: David Zimmer []

	libemu library was designed and written by: 
	 * Paul Baecher
	 * Markus Koetter

	special thanks go to:
	 * jt / for libdasm
	 * Tony Finch for
Source top

Windows Native Source/Binaries (201 hooks - current development branch)

*nix/Cygwin Source/Binaries (100 hooks - inactive) The older gcc compatible and cross-compilable version is available here: (tested with cygwin/gcc 3.4 & 4.3, RHEL 2.6/ gcc 4.1)