Degradation as DRM

by Nikolaos Tsapakis

Information available is for educational purposes only, views expressed are my own and do not necessarily reflect those of my employer.

Long time ago, while I was searching for interesting Digital Rights Management (DRM) systems on games, I came across FADE. 1

The protection allows the player to use the game normally.  Then it gradually degrades certain game features over time, like decreasing the accuracy of the player's weapons, eventually rendering it unplayable.

It seemed to me like an interesting exercise to introduce a similar custom protection as a binary patch in a game.

I selected LZDoom. 2  After downloading, you need to place a WAD3 file inside the main game directory in order to start the game.

The idea is to drop the game frame rate on a computer which is different than the game owner's computer based on an event.

That event is the player typing the idkfa cheat string during game play.

A different computer is been detected by the CPUID 4 instruction.  That hardware check is not very strict, but I believe it is fine for the purposes of the current article.

In order to discover which game code triggers on player cheat string input, I started the game and entered "idkfa", then noticed the string "Very Happy Ammo Added" on top of the screen.

Break pointing for read access on that particular string pauses game execution on code which gets executed in an event of a player cheat string input.  For dropping the game frame rate, I found the game's main loop and introduced a delay.  Delay may be introduced in different places inside the game's main loop.

The file for binary patching is lzdoom.exe having an MD5 value of: 61a2cd931fd3aaaae976e4131c512728

Binary analysis and patching was done using x64dbg. 5

Running tests between two different computers was done using a physical and a virtual machine on VirtualBox.  Following are the patches, description, and file raw offsets to patch.

You may use any hex editor to apply the patches.

patch_1:

; file offset 0x281FD6
; goto patch_2 player cheat string input event check
E9290F4500 jmp lzdoom_____prot.patch_2
90 nop
continue_2: <original game instructions>

patch_2:

; file offset 0x6D2F04
; save original registers
50 push rax
66:9C pushf
; rax points to cheat string
; compare string with "Very"
813856657279 cmp dword ptr ds:[rax],0x79726556
; if no string matches then continue game
75 0F jne lzdoom_____prot.continue_1
; if string matches then get delta
E8 00000000 call lzdoom_____prot.delta
delta:
58 pop rax
; rax points at the end of data section
48:05 DC745700 add rax, 0x5774DC
; set flag for later h/w check
C600 01 mov byte ptr ds:[rax],1
; restore original registers
continue_1:
66:9D popf
58 pop rax
; execute stolen code due to patch_1
48:8BF8 mov rdi,rax
48:85FF test rdi,rdi
; continue game
E9 AFF0BAFF jmp lzdoom_____prot.continue_2

patch_3:

; file offset 0x253C0
; go to patch_4 hardware check
E9 67DB6A00 jmp lzdoom_____prot.patch_4
90 nop
90 nop
90 nop
90 nop
continue_4: <original game instructions>

patch_4:

; file offset 0x6D2F2C
; save original registers
66:9C pushf
50 push rax
53 push rbx
51 push rcx
52 push rdx
E8 00000000 call lzdoom_____prot.delta_2
delta_2:
58 pop rax
48:05 B9745700 add rax,0x5774B9
; check if flag set by cheat string check
; If not set then continue game else check h/w
; processor info and feature bits
8038 01 cmp byte ptr ds:[rax],1
75 17 jne lzdoom_____prot.continue_3
48:33C0 xor rax,rax
48:FFC0 inc rax
0FA2 cpuid
; If h/w check fails introduce frame delay
81F9 0322989E cmp ecx,0x9E982203
74 07 je lzdoom_____prot.continue_3
B9 00101101 mov ecx,0x1111000
frame_drop:
E2 FE loop lzdoom_____prot.frame_drop
; restore original registers, execute stolen
; code due to patch_3 and continue game
continue_3:
5A pop rdx
59 pop rcx
5B pop rbx
58 pop rax
66:9D popf
57 push rdi ; stolen code
48:81EC 80000000 sub rsp0x80 ; stolen code
E9 5C2495FF jmp lzdoom_____prot.continue_4

References

  1. forum.exetools.com/showthread.php?t=13232
  2. github.com/drfrag666/gzdoom/releases/download/3.87b/LZDoom_3.87b_x64.zip
  3. github.com/Akbar30Bill/DOOM_wads
  4. en.wikipedia.org/wiki/CPUID
  5. x64dbg.com
Return to $2600 Index