Category Archives: Software

ultriX, a small ET hack in asm

On a rainy day, in a rare mood with nothing else to do, I set out to make a wallhack for that all time favourite online shooter, “Enemy Territory”.

You can download the sources here, or browse it here.

My goals and design constraints were the following,

  1. asm-only
  2. embed in the main game.exe with affecting its size
  3. include some media files
  4. keep size to a minimum

The source is pretty much self explanatory. There are however a few nice tricks I used which bear some singling out:

1) Use of thunks
When you want to call a function, you need to know its address. Normally, this is done automatically in the final stage of making an executable object by the linker. A trick called a thunk is used to still be able to call functions if you don’t at runtime know their address.

A stub function is used to load the current address into a register,

	mov ebx, [esp]

and then the function you want to call is preceded by a thunk-call, like this,

	call thunky_thunk
// ebx just got loaded with address pointing to this spot here!
	push ebp
	mov ebp, esp

// and the normal function you want to call (hook_EndFrame) continues...

Finally, at the start of the program, you can call all the

2) Identify usable storage space
Using existing resources, and barring heap allocations, puts constraints on the memory accessible to the payload without interfering (too much) with the program. One easily accessible source is to identify fixed length static (.data) strings. These are often initialized as char[1024] arrays, and the space after the terminating zero is free for use.

3) hide literals
A modified shader is used to display the image. The string to reference this shader is easily recognized by anti-cheat software. So instead of writing “punkbuster”, i write it in the following way,

	; sh_headtxt
	mov dword[sh_headtxt+0], 0x65646f6d
	mov dword[sh_headtxt+4], 0x702f736c
	mov dword[sh_headtxt+8], 0x6579616c
	mov dword[sh_headtxt+12], 0x682f7372
	mov dword[sh_headtxt+16], 0x682f6475
	mov dword[sh_headtxt+20], 0x2e646165
	mov dword[sh_headtxt+24], 0x33646d

4) modify an in-game shader for chams
Often the game is filled with unused chams. Pick one, and change it as you see fit. In this case, I just needed to modify the last part (0.25..) with spaces so as not to change the string length,

; now the complete shader text is @ address eax, safe to use
; fixed offset for the replacement part
; change fixed color directive "rgbGen const ( 0.25 0.25 0.25 )" to "rgbGen entity"
	mov dword [eax+222], 0x69746e65
	mov word [eax+226], 0x7974
	push eax
; blank with spaces
	lea edi, [eax+228]
	mov eax, 32
	mov ecx, 18
	rep stosb

	pop eax
	add esp, 4

5) logo compression/decompression
I created a 512×64 logo to display during the game. Normally, such a file is pretty big, compared to space in the .exe available to us. I used a compression scheme to only store non-black pixels and the single grayscale channel. Then I wrote the decompression function in C, and used gcc -c -Os option to generate the size-optimized code, and put this in the payload assembler file.

All in all, the image takes up a mere 4501 bytes.

Fuji Finepix remote control tool

I put my old Fuji S3 remote control project online, for whom it might interest. The files can be found here. Compile with

gcc -O2 s3.c -o s3

and run it without arguments to read the help file. Currently it supports the following commands,

  • Sensitivity/ISO
  • Exposure time (including BULB support)
  • Aperture
  • AF Mode
  • CCD Dynamic range mode
  • Exposure Program (A,P,S)
  • White Balance
  • Image quality (JPG, RAW, TIFF)
  • Tone mode
  • Sharpness
  • Colormode

Be sure to include support for the SCSI generic driver in the kernel, and use a kernel >= 2.6.30 because of bugs in the firewire stack.

The program can easily be extended to include support for more commands. First, add a command entry,

static const dc_fn_t dc_functions[] =
        0x8827, "Sensitivity", "Control camera sensitivity (ISO)", "i",
        dc_sensitivity, sizeof(dc_sensitivity)/sizeof(dc_sensitivity[0]),
        {32, 32}, 1, {2, }, dcc_set_handler, dcc_get_handler,

The first number, 0x8827 is the command (see the Fuji Reverse project page for a full list), “i” the cli option, and dc_sensitivity is the settings table, see below.

Normally the default function callbacks (dcc_set_handler, dcc_get_handler) ought to suffice. Finally you must add a settings table entry in s3shoot.h,

static const dc_index_t dc_sensitivity[] =
    {   {0, 0},  "100"    },
    {   {1, 0},  "160"    },
    {   {2, 0},  "200"    },
    {   {3, 0},  "400"    },
    {   {4, 0},  "800"    },
    {   {5, 0},  "1600"   },

Good luck! If you need any help, or would like to support me in adding support in Gphoto, leave a comment.