Writing a patch in ASM

Having problems with a specific game or application? Post your problems here!

Writing a patch in ASM

Postby Akuma » 2019-8-06 @ 10:01

Fella's,

I have a game that requires a patch to run properly, there is a bug and I do not want to touch the original exe.
After some googling I cant find much information on how to write one in ASM.

EDIT: I want to patch the program in memory, its compressed.

How do I go about this? (I am new to this)
Last edited by Akuma on 2019-8-08 @ 07:15, edited 1 time in total.
Akuma
Newbie
 
Posts: 56
Joined: 2019-7-24 @ 14:47

Re: Wrting a patch in ASM

Postby VileRancour » 2019-8-07 @ 16:02

You provide little information on what you're trying to do (or why a copy of the EXE won't do), but I'm inferring that you'd like to patch the game in-memory and then run it?

If so, a good start might be DOS function 4Bh/AL=1 (load but do not execute).
web  /   blog   /   tube
User avatar
VileRancour
Oldbie
 
Posts: 1723
Joined: 2003-5-14 @ 22:11
Location: 1-01-80 0:00a

Re: Wrting a patch in ASM

Postby ph4nt0m » 2019-8-07 @ 18:54

If you know the byte sequence to be patched, open the EXE in a hex editor of your choice, do the job and save as a copy.
User avatar
ph4nt0m
Member
 
Posts: 234
Joined: 2018-1-01 @ 19:03

Re: Wrting a patch in ASM

Postby kjliew » 2019-8-07 @ 20:18

Check out Binary diff/patch utilities
http://www.daemonology.net/bsdiff/
kjliew
Member
 
Posts: 480
Joined: 2004-1-08 @ 03:03

Re: Writing a patch in ASM

Postby Akuma » 2019-8-08 @ 07:25

VileRancour wrote:You provide little information on what you're trying to do (or why a copy of the EXE won't do), but I'm inferring that you'd like to patch the game in-memory and then run it?

If so, a good start might be DOS function 4Bh/AL=1 (load but do not execute).

My bad, I wasn't too clear about what I wanted, but yes I want to patch the game in-memory.

ph4nt0m wrote:If you know the byte sequence to be patched, open the EXE in a hex editor of your choice, do the job and save as a copy.

Forgot to mention that the executable is compressed, the byte sequence cannot be patched. I searched all files for it, I can only find it in memory. Also I think the file loads a couple of others files too. In-memory patching was what I was looking for.

kjliew wrote:Check out Binary diff/patch utilities http://www.daemonology.net/bsdiff/

Thank you, I will take a look.
Akuma
Newbie
 
Posts: 56
Joined: 2019-7-24 @ 14:47

Re: Writing a patch in ASM

Postby pantercat » 2019-8-08 @ 08:06

Akuma wrote:Forgot to mention that the executable is compressed, the byte sequence cannot be patched. I searched all files for it, I can only find it in memory. Also I think the file loads a couple of others files too. In-memory patching was what I was looking for.


I know what you mean. You have at least two ways to do it.
-write a TSR in ASM that captures some INT used by the executable you want to patch
-or capture INT and use the functions "Modify Allocated Memory Block" (INT 21h/4Ah) and "EXEC/Load and Execute Program" (INT 21h/4Bh).

Not long ago I wrote a couple of loaders to crack two games. The posts are in spanish, but I think the source code in ASM could be useful.

http://www.vlan7.org/2019/02/ms-dos-cra ... gador.html
http://www.vlan7.org/2019/04/haciendo-u ... -para.html

Happy reversing.
pantercat
Newbie
 
Posts: 29
Joined: 2018-9-06 @ 17:22

Re: Writing a patch in ASM

Postby Akuma » 2019-8-08 @ 09:02

That is extremely helpful, thank you sir.

What I got so far writing my first ASM program, is a simple 'Hello world'.
1. I need to figure out how to patch in-memory
2. When to patch, the executable needs to decompress itself first, otherwise whats the point.
3. I would probably have to wait for the OEP, then patch it, if it doesnt decompress and loads something else too.

Code: Select all
.MODEL TINY
.DATA
    msg db "Hello, world!$",0dh     ; [var] [declare bytes] "message$", no. bytes in hex
.CODE
    org 100h                                ; required by com file
START:
    mov ah, 09                            ; int21h: function print text
    lea dx, msg                           ; refer to msg to print
    int 21h

    mov ax, 4c00h                      ; return to dos
    int 21h
END START


I got it to produce a nice small com file with TASM.
Code: Select all
C:\>DEL TEST.MAP
 
C:\>DEL TEST.OBJ
 
C:\>DEL TEST.COM
 
C:\>TASM\BIN\TASM.EXE TEST.ASM TEST.OBJ
Turbo Assembler  Version 4.1  Copyright (c) 1988, 1996 Borland International
 
Assembling file:   TEST.ASM
Error messages:    None
Warning messages:  None
Passes:            1
Remaining memory:  466k
 
 
C:\>TASM\BIN\TLINK.EXE /t TEST.OBJ
Turbo Link  Version 7.1.30.1. Copyright (c) 1987, 1996 Borland International
 
C:\>test
Hello, world!
C:\>
 
Akuma
Newbie
 
Posts: 56
Joined: 2019-7-24 @ 14:47

Re: Writing a patch in ASM

Postby VileRancour » 2019-8-08 @ 13:19

A generic approach for in-memory patching is, if you tell DOS to load-but-do-not-execute the file, it is in memory and you get the segment address of the program's PSP; from there you can write to whatever locations you want within the program code. Of course, it's a good idea to test your planned patch first by using something like the DOSBox debugger to directly modify the routine in memory.

A compressed EXE is a whole different ballpark however. You might want to use some analysis tools to find out more (identify the packing scheme and perhaps find the original entry point). Ben Castricum's UNP may be a good place to start, along with its trace command "t".

I haven't tackled this before, but if I were to try writing such a loader, my approach might be to patch the unpacking code in-memory, so that once it's done unpacking (and is ready to jump to the OEP) it returns control to my loader. Then a second routine would patch the already-unpacked code in RAM with the required changes and make the jump.

Not sure if this is the best kind of project to tackle when at the hello-world level, but I did worse when I had less, so good luck. :D
web  /   blog   /   tube
User avatar
VileRancour
Oldbie
 
Posts: 1723
Joined: 2003-5-14 @ 22:11
Location: 1-01-80 0:00a

Re: Writing a patch in ASM

Postby ripsaw8080 » 2019-8-08 @ 14:07

A common method with patch TSRs/loaders is to set up an interrupt handler and watch for a particular function that is called after the target program's code is decrypted and/or decompressed, then modify memory relative to the interrupt's return address that was pushed on the stack. For example, programs often call INT 21h/30h to get the DOS version as one of the first things they do, but that's not necessarily the ideal function to watch for. It's a good idea to check the memory you intend to modify to see if it contains expected values, which ensures you're patching the right thing and also not performing the patch more than once.
User avatar
ripsaw8080
DOSBox Author
 
Posts: 4406
Joined: 2006-4-25 @ 23:24

Re: Writing a patch in ASM

Postby BloodyCactus » 2019-8-08 @ 14:25

yeah better to hook an interrupt vector, if the app was written in C you know its going to do a dos version check or anything is garunteed to do a memory realloc (0x4A). you can hook that and patch what you need to patch.
--/\-[ Stu : Bloody Cactus :: http://kråketær.com :: http://mega-tokyo.com ]-/\--
User avatar
BloodyCactus
Oldbie
 
Posts: 901
Joined: 2016-2-03 @ 13:34
Location: Lexington VA

Re: Writing a patch in ASM

Postby Akuma » 2019-8-08 @ 18:47

VileRancour wrote:A generic approach for in-memory patching is, if you tell DOS to load-but-do-not-execute the file, it is in memory and you get the segment address of the program's PSP; from there you can write to whatever locations you want within the program code. Of course, it's a good idea to test your planned patch first by using something like the DOSBox debugger to directly modify the routine in memory.

A compressed EXE is a whole different ballpark however. You might want to use some analysis tools to find out more (identify the packing scheme and perhaps find the original entry point). Ben Castricum's UNP may be a good place to start, along with its trace command "t".

I haven't tackled this before, but if I were to try writing such a loader, my approach might be to patch the unpacking code in-memory, so that once it's done unpacking (and is ready to jump to the OEP) it returns control to my loader. Then a second routine would patch the already-unpacked code in RAM with the required changes and make the jump.

Not sure if this is the best kind of project to tackle when at the hello-world level, but I did worse when I had less, so good luck. :D


Unpacking has never been a real problem for me, although there are some wonderful exceptions that still haunt me to this day.
(The INC loader from the Operation Wolf release iirc, thats a real nasty one)..ermm back to the topic at hand.

I plan on doing the following:
1. Write hello world
2. Write a patch for hello world, to: Hello patch!, that would hopefully cover the basics.
(debugging with dosbox debugger)
3. Deal with the unpacking, find the oep.
4. Write the patch, test and verify it.
5. Praise and glory!

I will take that luck sir!

ripsaw8080 wrote:A common method with patch TSRs/loaders is to set up an interrupt handler and watch for a particular function that is called after the target program's code is decrypted and/or decompressed, then modify memory relative to the interrupt's return address that was pushed on the stack. For example, programs often call INT 21h/30h to get the DOS version as one of the first things they do, but that's not necessarily the ideal function to watch for. It's a good idea to check the memory you intend to modify to see if it contains expected values, which ensures you're patching the right thing and also not performing the patch more than once.


I read through some code today from 'pantercat', they hooked into INT10. I think it was something like mov ax,3510h or something.
This is going to be hard on my brain =). Yes, one iteration, that's a good one. Noted.

BloodyCactus wrote:yeah better to hook an interrupt vector, if the app was written in C you know its going to do a dos version check or anything is garunteed to do a memory realloc (0x4A). you can hook that and patch what you need to patch.


Thank you, although most of this is 'hocus pocus' to me now. I'll get it to work eventually. I always do.:D
Akuma
Newbie
 
Posts: 56
Joined: 2019-7-24 @ 14:47

Re: Writing a patch in ASM

Postby Akuma » 2019-8-09 @ 08:18

I see that there are a lot of different ASM-compilers, I just found out that the syntax differs too.
So my question which one of them do you recommend I use and why? Thank you
  • MASM
  • TASM
  • A86
Akuma
Newbie
 
Posts: 56
Joined: 2019-7-24 @ 14:47

Re: Writing a patch in ASM

Postby BloodyCactus » 2019-8-09 @ 12:28

NASM unless your compiling it on a 286 or something. TASM would be the fallback if you dont want to learn NASM.
--/\-[ Stu : Bloody Cactus :: http://kråketær.com :: http://mega-tokyo.com ]-/\--
User avatar
BloodyCactus
Oldbie
 
Posts: 901
Joined: 2016-2-03 @ 13:34
Location: Lexington VA

Re: Writing a patch in ASM

Postby Akuma » 2019-8-10 @ 12:02

Hmm...its kinda working, but with a couple of issues.

1. It only works on my machine in dosbox, because its patching absolute, not relative ?
2. Its not stable, if I exit the game, the OS becomes unstable, it hangs second time around ?
3. I understand 80% of what I pieced together ?

If anyone can shed some light on this, Im all ears :D


Code: Select all
OVL     segment for 'code'
        assume cs:OVL, ds:OVL

org     100h                        ; output a .COM program

START:
mov     sp, 1024                 ; set stack pointer (size in bytes)
mov     bx, 1024/16             ; set bx=bytes/16, es=mem segment
mov     ah, 4ah                   ; change memory allocation
int     21h                           ; commit

mov     ax, 3521h               ; get OLDINT
int     21h                            ; commit

mov     OLDINT[0], bx         ; safe OLDINT to call later
mov     OLDINT[2], es         ; ?? no idea ??

mov     ax, 2521h                ; set NEWINT
lea     dx, NEWINT              ; with pointer to NEWINT proc far routine
int     21h

lea     bx, EXEC_INFO         ; ?? no idea ??
lea     dx, FILENAME           ; pointer to FILENAME
mov     ax, 4b00h                 ; load and run FILENAME
int     21h                             ; commit

mov     ax, 4c00h                 ; ah=exit, al=return code
int     21h                             ; commit

OLDINT  dw 0,0                    ; original INT

NEWINT  proc far
pushf                                   ; safe flags
cmp     dx, 029DAh               ; compare if INT is called with X
jnz     EXIT                          ; yes: goto CHECK, no: goto EXIT

CHECK:
push    bp                            ; safe 'bp'
mov     bp, sp                      ; 'bp' points to top of the stack
push    es                            ; safe 'es'
mov     es, [bp]                    ; copy bp to 'es'
cmp     word ptr es:[0XXXX], 0XXXXh ; if data matches search query
jne     RESTORE                  ; yes: goto PATCH , no: goto RESTORE

PATCH:                              ; --------------- patch -------------------
mov     byte ptr es:[0XXXX], 0XXh   ; change byte offset es:xxxx to xxxh
                                    ; ------------- end patch -----------------
   
RESTORE:
pop     es                          ; restore 'es'
pop     bp                          ; restore 'bp'

EXIT:
popf                                ; restore flags
jmp     dword ptr cs:[OLDINT]       ; jump to OLDINT

NEWINT endp

FILENAME    db "GAME.EXE",0      ; program to execute
EXEC_INFO   db 22 DUP (0)           ; ?? no idea : 22x 00h for what ??

OVL ends
end START


Is there a way to use a fixed font for the code window ?
Attachments
PATCHASM.ZIP
(996 Bytes) Downloaded 6 times
Akuma
Newbie
 
Posts: 56
Joined: 2019-7-24 @ 14:47

Re: Writing a patch in ASM

Postby VileRancour » 2019-8-10 @ 12:38

At a first glance, it looks like you aren't setting up the interrupt chain correctly. Keep in mind that an "INT XXh" instruction pushes the flags onto the stack, then the far return address (dword), then jumps to the interrupt handler. The handler routine normally ends with an IRET instruction, which does the reverse (pops the CS:IP then the flags, and resumes).

So to properly call the old interrupt handler, your EXIT section should emulate the INT instruction by pushing the flags (PUSHF) and the far return address (e.g. PUSH CS, then CALL a far jump to the old handler, which pushes IP during the CALL). Then once the old handler returns (with an IRET), your NEWINT should also terminate with an IRET, since it also gets called with "INT XXh" and has to preserve the expected state. This also means there's no need for the existing PUSHF/POPF pair.

This might be some relevant reading material: https://web.archive.org/web/20080222000 ... oehrl.html. There may be other issues, but I'd start with that.

(Edit:) also, your EXEC_INFO structure should contain a parameter block as described here: http://faydoc.tripod.com/structures/15/1590.htm - it's probably a good idea to actually set up the values. ;) More info here: http://www.ctyme.com/intr/rb-2939.htm
web  /   blog   /   tube
User avatar
VileRancour
Oldbie
 
Posts: 1723
Joined: 2003-5-14 @ 22:11
Location: 1-01-80 0:00a

Re: Writing a patch in ASM

Postby BloodyCactus » 2019-8-10 @ 14:44

you cant do a 4c exit whilst trapping int21, you need to release your int21 hook back to its original values before you exit.
your execinfo needs to be valid with fcb/psp pointers, cli, etc
--/\-[ Stu : Bloody Cactus :: http://kråketær.com :: http://mega-tokyo.com ]-/\--
User avatar
BloodyCactus
Oldbie
 
Posts: 901
Joined: 2016-2-03 @ 13:34
Location: Lexington VA


Return to DOSBox Games/Apps

Who is online

Users browsing this forum: No registered users and 1 guest