Quantcast
Jump to content
Search In
  • More options...
Find results that contain...
Find results in...
    1. Welcome to GTAForums!   (85,001 visits to this link)

    2. News

    1. GTA Online

      1. Find Lobbies & Players
      2. Guides & Strategies
      3. Vehicles
      4. Content Creator
      5. Help & Support
    2. Crews

      1. Events
      2. Recruitment
    1. Grand Theft Auto Series

    2. GTA Next

    3. GTA V

      1. PC
      2. Guides & Strategies
      3. Help & Support
    4. GTA IV

      1. Episodes from Liberty City
      2. Multiplayer
      3. Guides & Strategies
      4. Help & Support
      5. GTA Mods
    5. GTA Chinatown Wars

    6. GTA Vice City Stories

    7. GTA Liberty City Stories

    8. GTA San Andreas

      1. Guides & Strategies
      2. Help & Support
      3. GTA Mods
    9. GTA Vice City

      1. Guides & Strategies
      2. Help & Support
      3. GTA Mods
    10. GTA III

      1. Guides & Strategies
      2. Help & Support
      3. GTA Mods
    11. Top Down Games

      1. GTA Advance
      2. GTA 2
      3. GTA
    12. Wiki

      1. Merchandising
    1. GTA Modding

      1. GTA V
      2. GTA IV
      3. GTA III, VC & SA
      4. Tutorials
    2. Mod Showroom

      1. Scripts & Plugins
      2. Maps
      3. Total Conversions
      4. Vehicles
      5. Textures
      6. Characters
      7. Tools
      8. Other
      9. Workshop
    3. Featured Mods

      1. DYOM
      2. OpenIV
      3. GTA: Underground
      4. GTA: Liberty City
      5. GTA: State of Liberty
    1. Red Dead Redemption 2

    2. Red Dead Redemption

    3. Rockstar Games

    1. Off-Topic

      1. General Chat
      2. Gaming
      3. Technology
      4. Programming
      5. Movies & TV
      6. Music
      7. Sports
      8. Vehicles
    2. Expression

      1. Graphics / Visual Arts
      2. GFX Requests & Tutorials
      3. Writers' Discussion
      4. Debates & Discussion
    1. Forum Support

    2. Site Suggestions

Sign in to follow this  
lpgunit

Using Detours/EasyHook in an .ASI?

Recommended Posts

lpgunit

Yeah, I know I am not that well versed with C++ or programming as of now, but I'm trying to cobble this up as a simple fix of sorts. Sure, ASIs are most commonly associated with GTA, but this has little to do with the series so I'll leave this here.

 

See, I have this 1990s era game which ran off Win9x properly, but not on 2000 and later due to changes in the API, specifically on how CreateWindowEx is used. Running the game through both Wine and an API debugger reveals it's calling an invalid menu handle, which I assume is either an oversight on the developer's part, or Microsoft moving goalposts. There aren't any drop down menus or menu bars in the game, so I assume hMenu should be NULL, yet the programmers used 1 or 0x1 as a value.

 

I am trying to experiment on this by using an ASI mod to hook into the game process and alter the API function so it runs properly, but I'm at a loss as to how to use either Detours or EasyHook to alter things.

 

Here's one thread on Stackoverflow regarding CreateWindowEx, though it doesn't appear to pertain to DLLs/ASIs: http://stackoverflow.com/questions/7770520/can-windows-api-functions-be-over-written-and-called-after-it

Share this post


Link to post
Share on other sites
K^2

ASI worked with early 3D GTA games because they read additional libraries at startup. Later games in the series relied on a DirectX injector introducing code to load ASI files. The format was kept simply because people who wrote them were used to ASIs.

 

If you are hooking into a Win98 game, none of these loaders are going to work. On the other hand, you seem to have already found the function you are trying to hook, so writing your own injector is a piece of cake. You have two routes. You can either modify the CreateWindowEx function itself, by clobbering function prologue with a jump to a new prologue, or you can modify the calling function. In that case, you can either find the place where it passes a bad argument and change it (if it's a constant), or call your own wrapper for CreateWindowEx that will fix the parameters.

 

The function you will be mostly using is WriteProcessMemory. You can pass to it any valid process handle. You can get the process handle by either calling OpenProcess or by starting the process yourself. Basically, it depends on whether you want your program to run side-by-side or work as a launcher. Either way, once you have process handle, you need to find the virtual address of the function you are trying to modify. This will be a constant offset from the module base.

 

Now, there are effectively two ways of going about this. You can do all your surgery from remote process (launcher, w/e.). That makes work easy, but you first need to get the base address of the image of the target process. You do that with a call to EnumProcessModules and grabbing module whose name matches that of the image. In other words, name of the executable. The hModule pointer is actually the base address you want, but you can get additional info with GetModuleInformation.

 

Second option is injecting payload into target process. You can use CreateRemoteThread to force target to run your code. You usually want to make it a DLL, so that all of its linking is dynamic. This is how most basic DLL/ASI injectors actually work under the hood. Since your code now runs inside the target process, you just call GetModuleHandle(NULL) to get the base address for the image.

 

From there, it's easy. You know location of your functions relative to module base, so just add the hModule to the offset and use the WriteProcessMemory to change whatever you need. If you need to add a jump instruction anywhere see the x86 JMP reference. If you need to write a wrapper function with no prologue of its own, __declspec(naked) should do the trick in MSVC.

Share this post


Link to post
Share on other sites
lpgunit

The game used Ddraw and since ThirteenAG's loader seemed to work with it I thought of giving it a try.

Share this post


Link to post
Share on other sites
K^2

Well, see if it works. Make a DLL that pops up a MessageBox on load. If it does, saves you a little bit of work in writing your own injector.

 

Either way, though, you'll have to write your own hooks and place them with WriteProcessMemory.

Share this post


Link to post
Share on other sites
lpgunit

Well, see if it works. Make a DLL that pops up a MessageBox on load. If it does, saves you a little bit of work in writing your own injector.

 

Either way, though, you'll have to write your own hooks and place them with WriteProcessMemory.

As a matter of fact, I did use this code snippet LINK2012 made for the lulz:

http://gtaforums.com/topic/517994-creating-asi-files-for-gta-sa/?do=findComment&comment=1061507590

 

It displays a message box as I expected:

RSUgWbw.jpg

 

What I'm wondering is how to inject the game just for a single function. EasyHook seemed fit for my needs as I don't feel like going Rube Goldbergian for just one show-stopper, but the problem is I couldn't get it to hook properly yet:

https://github.com/EasyHook/EasyHook/issues/134

 

Hope you don't mind, but I also sent you a Skype request so I can further expound my problem to you. :)

Edited by lpgunit

Share this post


Link to post
Share on other sites
K^2

Well, there you go then. Now see if you can hook the function you are trying to modify. Simplest thing you can do for testing is write a single byte 0xCC to the function's address. This is an INT 3 instruction which causes a software breakpoint. If you have debugger attached to the process you've hooked, it will stop execution on that function. This will make it easy to see where the function is being called from and what are the parameters that are being passed.

 

Edit: Didn't see the text at the bottom. Ok, first of all, test to see what the returns are for GetModuleHandle. Make sure you are actually getting a module. Then see if you are also getting a valid address with GetProcAddress. You can keep using the MessageBox to print debug info.

 

Edit2: By the way, that 0x01 passed as hMenu, is it a constant, or does it come from one of the registers? I'm wondering if you aren't just stepping on a debugger trap.

Share this post


Link to post
Share on other sites
lpgunit

Well, there you go then. Now see if you can hook the function you are trying to modify. Simplest thing you can do for testing is write a single byte 0xCC to the function's address. This is an INT 3 instruction which causes a software breakpoint. If you have debugger attached to the process you've hooked, it will stop execution on that function. This will make it easy to see where the function is being called from and what are the parameters that are being passed.

 

Edit: Didn't see the text at the bottom. Ok, first of all, test to see what the returns are for GetModuleHandle. Make sure you are actually getting a module. Then see if you are also getting a valid address with GetProcAddress. You can keep using the MessageBox to print debug info.

 

Edit2: By the way, that 0x01 passed as hMenu, is it a constant, or does it come from one of the registers? I'm wondering if you aren't just stepping on a debugger trap.

I'm not sure on why the game uses 0x01 tbh, except it seems to call for a nonexistent menu as no context or menu bars exist within the game. Maybe the programmers just used it out of random, not caring about potential NT compatibility as the NT/2000 series wasn't marketed towards average end users back then.

Edited by lpgunit

Share this post


Link to post
Share on other sites
K^2

I sent you a PM, because I don't want to drop a ton of code in here. Let me know how that works out or if you have any problems with it.

Share this post


Link to post
Share on other sites
lpgunit

Didn't mean to make you go through all the trouble and all, but thanks anyway. I'll see what I can do from here.

Share this post


Link to post
Share on other sites
lpgunit

And yeah, turns out I was right all along, and the game's fixed.

 

The American Girls Dress Designer used to be like this whenever I click print, load a saved outfit, quit or basically anything that invokes a new popup window:

UZfnn7V.gif

 

And with the .ASI, it now works as it should:

U2D4EMn.jpg

Edited by lpgunit

Share this post


Link to post
Share on other sites
lpgunit

Sorry for the triple-post, but I'd like to share this as it's something of an epic/funny fail on part of the programmers: The game doesn't work on Windows NT 4.0 either! To think that NT4 was released a few years before this game was even developed.

 

So that more or less confirms it: from what it seems, the developers never intended to make Dress Designer compatible with NT at all. It figures as few if any families would even bother having a workstation OS installed on their rigs anyway, but when the NT line came to home systems through XP, lulz ensued. :p

Edited by lpgunit

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×

Important Information

By using GTAForums.com, you agree to our Terms of Use and Privacy Policy.