Flat Assembler Extras
These page contains various include files, interesting macros, and modifications to FASM.
Sections
Macros and Include Files
The base package for FASM contains many useful macros to construct Windows resource sections, import tables, etc. The include files also cover the base of the Win32 platform. To complement this base set, I created another package that contains more macros, and definitions for more Win32 features. You can download it here.
Extract the package to the root of your FASM installation.
The package also contains INCLUDE/EQUATES/TLHELP32.INC, which is a hand-translated include file of the Toolhelp APIs (tlhelp32.h).
The INCLUDE/WIN32AM.INC and INCLUDE/WIN32WM.INC are my minimal include files. These are virtually identical to the INCLUDE/WIN32A.INC and INCLUDE/WIN32W.INC files in the base FASM package, except mine don't automatically include everything under INCLUDE/EQUATES/. This speeds up compilation.
The INCLUDE/MACRO/macros.inc is a macro file with many useful macros for debugging, such as quickly showing a message box with some integer value. Here is a complete example:
; using macros ; 04.07.2008 format PE GUI 4.0 entry start include "%include%/win32a.inc" include "%include%/macro/macros.inc" ; include our magic macros file section ".code" code readable executable start: push ebx esi edi ; ; Show a fixed string messagebox. ; showmsg "Hello!" ; ; Show a simple integer. ; mov ebx,-5 showint "value of ebx in decimal",ebx showuint "value of ebx in unsigned decimal",ebx showhex "value of ebx in hexadecimal",ebx ; ; Show a string pointer. ; mov ebx,Hello showstr "string pointed to by ebx",ebx msgbox ebx ; ; Show a custom-formatted message. ; mov ebx,Hello mov esi,10 mov edi,17 showfmt "ebx is '%s',esi is %u, and edi is %u",ebx,esi,edi ; ; Set the last error to 'Access denied.' ; stdcall [SetLastError],5 lasterr ; ; The following macros generate simple code to convert a 7-bit ASCII character to uppercase/lowercase. ; mov al,'a' ucase al ; al is now 'A' lcase al ; al is now back to 'a' pop edi esi ebx stdcall [ExitProcess],0 section ".data" data readable writeable import library kernel32,"kernel32.dll",user32,"user32.dll" include "%include%/api/kernel32.inc" include "%include%/api/user32.inc" ; ; Use the DATE and TIME variables that were defined by macros.inc to record the date and time this file ; was compiled at. Credits to Privalov for the date conversion macros. ; Hello db "hallo! this was compiled at: ",DATE," ",TIME,0
Running this code will produce a series of message boxes displaying the needed values.
IDE Modifications
This section contains some modifications I made to the FASM IDE for Windows (FASMW.EXE). Notably:
- Add configurable, external debugger support. You configure the path to your debugger, press F8, and the IDE will automatically compile the file, and launch the debugger.
- Display the name of the file being currently editted in the program's title bar.
- Default all "Save modified file?" message boxes to 'Yes'. For some reason, the author decided there are times when you don't want to save your changes by default. This differs from other applications which always pick the safest option: save your work.
- Show the length of currently selected text in the status bar. This is useful in measuring string lengths quickly, and then using them somewhere in the code.
- Map Ctrl-W to close file. This is a common keyboard shortcut that FASMW IDE does not have.
- Unmap Escape from closing the file. I frequently press Esc to close some dialog, and end-up closing the IDE by mistake.
- Change the GUI font to Tahoma, instead of Win95-esque MS Sans Serif.
You can download the modified FASMW.EXE binary file here (55 KB), version 0.93.15.1 (that is, the 0.93.15.0 that comes with FASM 1.67.26, plus these modifications).
Alternatively, you can compile it yourself. Get the base FASMW 1.67.26 distribution, and apply the following diff file using GNU's patch utility. The patch is relative to FASM/SOURCE, so apply the patch from that directory, like so patch.exe -p3 <fasmw-0.93.15.1.patch. After applying the patch, simply recompile SOURCE/IDE/FASMW/FASMW.ASM.
Gems
This section contains various gems and tricks possible with FASM, mostly thanks due its advanced macro capabilities.
Code Obfuscation
This trick involves creating macros that override the default behaviour of various common instructions, such as jmp, call, add, etc. The overriden instruction preserves the functionality of the original instruction, with some extra junk that makes the disassembly much harder to read and analyze, even for advanced disassemblers such as IDA.
Consider the following macro:
macro add dest,src {
local .._add,.._over,.._quit
jmp .._over
db $E9
.._add:
add dest,src
jmp .._quit
.._over:
jmp .._add
db $EB
.._quit:
In this macro, we create a junk jmp ($E9) opcode just before the actual add instruction. When a disassembler processes this code, it will miss the add instruction, and actually disassemble some junk jump that makes no sense. Obviously, the code size blows up and performance decreases with this kind of substitution macro.
I originally pioneered this technique as part of the protection in Lokomotiv trainer engine project. Here is the full set of substitution macros that I created for it:
macro jmp dest { push dest retn db $E9 } macro call dest { local ..ret push ..ret jmp dest ..ret: } macro mov dest,src { local .._mov,.._over,.._quit jmp .._over db $EB .._mov: mov dest,src jmp .._quit .._over: jmp .._mov db $74 .._quit: } macro add dest,src { local .._add,.._over,.._quit jmp .._over db $E9 .._add: add dest,src jmp .._quit .._over: jmp .._add db $EB .._quit: } macro sub dest,src { local .._sub,.._over,.._quit jmp .._over db $75 .._sub: sub dest,src jmp .._quit .._over: jmp .._sub db $0F,$85 .._quit: } macro cmp dest,src { local .._cmp,.._over,.._quit jmp .._over db $0F,$84 .._cmp: cmp dest,src jmp .._quit .._over: jmp .._cmp db $7A .._quit: }
Simply paste these macros into a separate file and include it before your code, and then assemble your program with FASM as usual. Disassemble the output file to see the abomination.
Self-Encrypting Code
This is another technique I created as part of the protection for the Lokomotiv trainer engine project in early 2004. Coincidentally, someone had the same idea on the FASM board a couple of months later.
This technique involves FASM's ability to manipulate the bytes of the code it had already assembled. In this case, we use a simple cryptor to encrypt a chunk of assembled code during compile time. At run-time, we run a short loop that decrypts the code in memory.
Consider a simple Hello World message box, with the encrypting macro setup:
; selfencrypt ; 04.07.2008 format PE GUI 4.0 entry start include "%include%/win32a.inc" ; ; This is the encryption macro. ; It is a simple XOR with 0xAA (10101010 in binary). ; macro encrypt dstart,dsize { local ..char,..key,..shift repeat dsize load ..char from dstart+%-1 ..char = ..char xor $AA store ..char at dstart+%-1 end repeat } section ".code" code readable writeable executable start: ; ; This will be the only non-encrypted part of the code. ; Here we will decrypt the code at run-time. ; mov edx,real_start xor eax,eax mov ecx,code_size @@: xor byte [edx],$AA inc edx loop @B real_start: ; ; Everything from here on will be encrypted. ; stdcall [MessageBox],0,HelloWorld,HelloWorld,MB_ICONASTERISK stdcall [ExitProcess],0 ; ; Encrypt everything from real_start to here. ; display "Encrypting code... " code_size = $ - real_start encrypt real_start,code_size display "done",13,10 section ".data" data readable writeable import library kernel32,"kernel32.dll",user32,"user32.dll" include "%include%/api/kernel32.inc" include "%include%/api/user32.inc" HelloWorld db "Hello World!",0
One particular thing to note is that the .code section is marked as writeable. This is needed so the code can be decrypted and written back at run-time.
You can find a more elaborate encryption algorithm as part of Lokomotiv trainer engine.
Past Versions
This sections contains an archive of past versions of FASM. The author used to keep a limited archive here, but it is no longer maintained. Here is mine (thanks to FASM forum members for helping me build it):
Name | Description | Date | Size |
---|---|---|---|
fasmw16727.zip | 2008-07-13 | 820.3 KB | |
fasm16727.zip | 2008-07-13 | 272.2 KB | |
fasm-1.67.27.tar.gz | 2008-07-12 | 190.1 KB | |
fasm-1.67.27.tgz | 2008-07-12 | 182.4 KB | |
fasmw16726.zip | 2008-01-29 | 819.9 KB | |
fasm16726.zip | 2008-01-29 | 271.8 KB | |
fasm-1.67.26.tar.gz | 2008-01-28 | 186.2 KB | |
fasm-1.67.26.tgz | 2008-01-28 | 180.3 KB | |
fasm-1.67.25.tar.gz | 2007-12-31 | 181.5 KB | |
fasm-1.67.25.tgz | 2007-12-31 | 178.2 KB | |
fasmw16725.zip | 2007-12-31 | 826.6 KB | |
fasm16725.zip | 2007-12-31 | 275.9 KB | |
fasm-1.67.24.tgz | 2007-12-05 | 178.1 KB | |
fasm-1.67.24.tar.gz | 2007-12-05 | 181.4 KB | |
fasmw16724.zip | 2007-12-05 | 826.4 KB | |
fasm16724.zip | 2007-12-05 | 275.8 KB | |
fasmw16723.zip | 2007-11-11 | 823.2 KB | |
fasm-1.67.23.tgz | 2007-11-10 | 176.0 KB | |
fasm-1.67.23.tar.gz | 2007-09-08 | 178.9 KB | |
fasm16723.zip | 2007-09-08 | 272.7 KB | |
fasmw16722.zip | 2007-08-06 | 822.6 KB | |
fasm16722.zip | 2007-08-06 | 272.2 KB | |
fasm-1.67.22.tar.gz | 2007-08-06 | 178.4 KB | |
fasm-1.67.22.tgz | 2007-08-06 | 175.5 KB | |
fasmw167.zip | 2007-03-11 | 821.5 KB | |
fasmw166.zip | 2006-06-02 | 764.1 KB | |
fasmw165.zip | 2006-02-21 | 757.4 KB | |
fasmw164-8.zip | 2005-12-09 | 745.8 KB | |
fasm164.zip | 2005-12-09 | 175.4 KB | |
fasmw164-9.zip | 2005-10-28 | 745.8 KB | |
fasm-1.6.4-libc.tgz | 2005-08-14 | 106.2 KB | |
fasm162.zip | 2005-06-27 | 165.6 KB | |
fasm160.zip | 2005-03-15 | 162.0 KB | |
fasm159.zip | 2005-02-20 | 191.5 KB | |
fasmw158.zip | 2005-02-12 | 638.9 KB | |
fasm158.zip | 2005-02-12 | 154.1 KB | |
fasm157.zip | 2005-01-19 | 153.1 KB | |
fasm156.zip | 2004-11-24 | 154.2 KB | |
fasm155.zip | 2004-09-12 | 155.9 KB | |
fasm154-8.zip | 2004-08-18 | 152.9 KB | |
fasmw154-7.zip | 2004-08-04 | 586.5 KB | |
fasm-1.54-7.tar.gz | 2004-08-04 | 142.4 KB | |
fasm154-7.zip | 2004-08-04 | 153.2 KB | |
fasmc154-7.zip | 2004-08-04 | 154.7 KB | |
fasm-1.54-5.tar.gz | 2004-08-03 | 142.2 KB | |
fasmw154-5.zip | 2004-08-03 | 586.4 KB | |
fasm154-5.zip | 2004-08-03 | 153.1 KB | |
fasmc154-5.zip | 2004-08-03 | 154.6 KB | |
fasm153.zip | 2004-07-22 | 151.0 KB | |
fasm152-26.zip | 2004-05-06 | 150.8 KB | |
fasmw152-26.zip | 2004-05-06 | 580.8 KB | |
fasmw152.zip | 2004-04-27 | 572.8 KB | |
fasm152-24.zip | 2004-04-27 | 150.9 KB | |
fasmc152.zip | 2004-04-27 | 152.3 KB | |
fasm-1.52.tar.gz | 2004-04-21 | 140.1 KB | |
fasm-1.51.tar.gz | 2004-02-16 | 139.2 KB | |
fasmc151.zip | 2004-02-16 | 150.5 KB | |
fasmw151.zip | 2004-02-16 | 562.0 KB | |
fasm151-2.zip | 2004-02-16 | 148.9 KB | |
fasm151.zip | 2004-01-31 | 148.7 KB | |
fasm-1.43.tar.gz | 2003-12-29 | 126.5 KB | |
fasm-1.50.tar.gz | 2003-12-08 | 136.1 KB | |
fasm150.zip | 2003-12-08 | 146.9 KB | |
fasmw150.zip | 2003-12-08 | 557.2 KB | |
fasmc150.zip | 2003-12-08 | 148.4 KB | |
fasmw149.zip | 2003-10-14 | 551.3 KB | |
fasmc149.zip | 2003-10-14 | 143.7 KB | |
fasm149.zip | 2003-10-14 | 142.4 KB | |
fasm-1.49.tar.gz | 2003-10-13 | 131.8 KB | |
fasmw149-090.zip | 2003-09-14 | 548.2 KB | |
fasm148.zip | 2003-08-25 | 236.8 KB | |
fasm-1.47.tar.gz | 2003-06-28 | 128.2 KB | |
fasmw147.zip | 2003-06-28 | 544.2 KB | |
fasm147.zip | 2003-06-28 | 234.9 KB | |
fasm146.zip | 2003-04-09 | 234.6 KB | |
fasmw146.zip | 2003-04-09 | 542.3 KB | |
fasm-1.46.tar.gz | 2003-04-08 | 125.8 KB | |
fasmw145.zip | 2003-02-09 | 571.2 KB | |
fasm145-2.zip | 2003-02-09 | 234.3 KB | |
fasm-1.45.tar.gz | 2003-02-08 | 125.9 KB | |
fasm145.zip | 2003-02-06 | 234.4 KB | |
fasm144.zip | 2003-01-19 | 234.5 KB | |
fasm143-26.zip | 2003-01-10 | 233.7 KB | |
fasmw143.zip | 2003-01-08 | 357.6 KB | |
fasm143-16.zip | 2002-12-30 | 262.2 KB | |
fasm-1.42.tar.gz | 2002-12-04 | 120.3 KB | |
fasmw142.zip | 2002-12-04 | 170.3 KB | |
fasm142.zip | 2002-12-04 | 251.9 KB | |
fasmw141-045.zip | 2002-11-22 | 170.3 KB | |
fasm141.zip | 2002-11-21 | 251.6 KB | |
fasmw141-041.zip | 2002-11-14 | 168.5 KB | |
fasm141-19.zip | 2002-11-14 | 251.4 KB | |
fasm-1.41.tar.gz | 2002-11-14 | 120.1 KB | |
fasm140.zip | 2002-08-21 | 201.1 KB | |
fasm140-20.zip | 2002-08-21 | 201.1 KB | |
fasm140.tar.gz | 2002-08-20 | 82.2 KB | |
fasm139.zip | 2002-07-09 | 203.5 KB | |
fasm139.tar.gz | 2002-07-09 | 89.1 KB | |
fasm137.zip | 2002-06-12 | 195.7 KB | |
fasm136.zip | 2002-05-23 | 169.7 KB | |
fasm135.zip | 2002-05-06 | 167.4 KB | |
fasm134.zip | 2002-04-19 | 168.5 KB | |
fasm132.zip | 2002-03-06 | 167.2 KB | |
fasm131.zip | 2002-02-03 | 166.0 KB | |
fasm120.zip | 2001-11-18 | 145.0 KB | |
fasm114.zip | 2001-10-17 | 142.7 KB | |
fasm113.zip | 2001-08-23 | 142.3 KB | |
fasm111.zip | 2001-06-25 | 118.7 KB | |
fasm110.zip | 2001-03-22 | 119.0 KB | |
fasm130.zip | 2001-01-18 | 164.6 KB | |
fasm109.zip | 2001-01-04 | 114.7 KB | |
fasm108-repaired.zip | 2000-11-16 | 116.2 KB | |
fasm108-corrupt.zip | 2000-11-16 | 114.3 KB | |
fasm107.zip | 2000-10-19 | 114.1 KB | |
fasm106.zip | 2000-08-23 | 109.7 KB | |
fasm105.zip | 2000-08-16 | 108.8 KB | |
fasm104.zip | 2000-08-10 | 108.1 KB | |
fasm103.zip | 2000-07-15 | 61.5 KB | |
fasm102.zip | 2000-07-02 | 62.9 KB | |
fasm101.zip | 2000-06-27 | 60.8 KB | |
fasm10.zip | 2000-05-28 | 60.8 KB |
Comments
[an error occurred while processing this directive]