» »

[c++]Pridobivanje naslova objekta iz virtualne funkcije

[c++]Pridobivanje naslova objekta iz virtualne funkcije

Klobasa ::

Lp!

Imam manjši problem pri pisanju modifikacije za igro Counter Strike - Source. Moj končni produkt je dll datoteka, katera je inject-ana v hl2.exe process, problem pa je sledeči.


CHCClient razred je razred del source engine-a. Razred vsebuje tako na oko okoli 50 virtualnih metod. Naslov globalnega objekta tega razreda mi je znan.

class CHLClient : public IBaseClientDLL
{
public:
	virtual int  Init( CreateInterfaceFn appSystemFactory, CreateInterfaceFn physicsFactory, CGlobalVarsBase *pGlobals ); // index 0
.
.
.
	virtual void HudUpdate( bool bActive ); // index 9
}


Init funkcijo ( index 0 ) engine uporabi na začetku ob zagonu igre za inicializacijo nekaterih objektov. funkcija izgleda tako ( cp iz hl2 source-a, skrajšana verzija ).

 int CHLClient::Init( CreateInterfaceFn appSystemFactory, CreateInterfaceFn physicsFactory, CGlobalVarsBase *pGlobals )
{
	InitCRTMemDebug();
	MathLib_Init( 2.2f, 2.2f, 0.0f, 2.0f );

	// Hook up global variables
	gpGlobals = pGlobals;

	ConnectTier1Libraries( &appSystemFactory, 1 );
	ConnectTier2Libraries( &appSystemFactory, 1 );
	ConnectTier3Libraries( &appSystemFactory, 1 );
}



IDA view Init funkcije:

                        ; =============== S U B R O U T I N E =======================================
.text:10070FE0
.text:10070FE0                         ; Attributes: bp-based frame
.text:10070FE0
.text:10070FE0                         ; int __thiscall CHLClient__Init(CHLClient *this, void *(__cdecl *appSystemFactory)(const char *, int *), void *(__cdecl *physicsFactory)(const char *, int *), CGlobalVarsBase *pGlobals)
.text:10070FE0                         ?Init@CHLClient@@UAEHP6APAXPBDPAH@Z2PAVCGlobalVarsBase@@@Z proc near
.text:10070FE0                                                                 ; DATA XREF: .rdata:const CHLClient::`vftable'o
.text:10070FE0
.text:10070FE0                         var_28          = dword ptr -28h
.text:10070FE0                         var_24          = dword ptr -24h
.text:10070FE0                         var_20          = dword ptr -20h
.text:10070FE0                         factories       = factorylist_t ptr -8
.text:10070FE0                         appSystemFactory= dword ptr  8
.text:10070FE0                         physicsFactory  = dword ptr  0Ch
.text:10070FE0                         pGlobals        = dword ptr  10h
.text:10070FE0
.text:10070FE0                         this = ecx
.text:10070FE0 55                                      push    ebp
.text:10070FE1 8B EC                                   mov     ebp, esp
.text:10070FE3 83 EC 08                                sub     esp, 8
.text:10070FE6 E8 65 1F 07 00                          call    ?NetworkStateChanged@tonemap_params_t@@UAEXXZ ; tonemap_params_t::NetworkStateChanged(void)
.text:10070FEB D9 EE                                   fldz
.text:10070FED 6A 01                                   push    1               ; bAllowMMX
.text:10070FEF 6A 01                                   push    1               ; bAllowSSE2
.text:10070FF1 6A 01                                   push    1               ; bAllowSSE
.text:10070FF3 6A 01                                   push    1               ; bAllow3DNow
.text:10070FF5 6A 02                                   push    2               ; overbright
.text:10070FF7 83 EC 0C                                sub     esp, 0Ch
.text:10070FFA D9 5C 24 08                             fstp    [esp+28h+var_20]
.text:10070FFE D9 05 28 40 30 10                       fld     ds:__real@400ccccd
.text:10071004 D9 54 24 04                             fst     [esp+28h+var_24]
.text:10071008 D9 1C 24                                fstp    [esp+28h+var_28]
.text:1007100B E8 B0 ED 17 00                          call    ?MathLib_Init@@YAXMMMH_N000@Z ; MathLib_Init(float,float,float,int,bool,bool,bool,bool)
.text:10071010 8B 45 10                                mov     eax, [ebp+pGlobals]
.text:10071013 8D 4D 08                                lea     this, [ebp+appSystemFactory]
.text:10071016 6A 01                           




HudUpdate funkcijo ( index 9 ) engine uporablja za updejtat panel-e itd...

void CHLClient::HudUpdate( bool bActive )
{
	float frametime = gpGlobals->frametime;

	GetClientVoiceMgr()->Frame( frametime );

	gHUD.UpdateHud( bActive );
.
.
}



IDA view HudUpdate funkcije:

                         ; =============== S U B R O U T I N E =======================================
.text:10070880
.text:10070880                         ; Attributes: bp-based frame
.text:10070880
.text:10070880                         ; void __thiscall CHLClient__HudUpdate(CHLClient *this, bool bActive)
.text:10070880                         ?HudUpdate@CHLClient@@UAEX_N@Z proc near
.text:10070880                                                                 ; DATA XREF: .rdata:103040E8o
.text:10070880
.text:10070880                         var_10          = qword ptr -10h
.text:10070880                         frametime       = dword ptr -4
.text:10070880                         bActive         = byte ptr  8
.text:10070880                         boneaccess      = C_BaseAnimating::AutoAllowBoneAccess ptr  0Bh
.text:10070880
.text:10070880                         this = ecx
.text:10070880 55                                      push    ebp
.text:10070881 8B EC                                   mov     ebp, esp
.text:10070883 51                                      push    this
.text:10070884 A1 DC 05 3E 10                          mov     eax, ?gpGlobals@@3PAVCGlobalVarsBase@@A.m_Index ; CGlobalVarsBase * gpGlobals
.text:10070889 D9 40 10                                fld     dword ptr [eax+10h]
.text:1007088C 56                                      push    esi
.text:1007088D 83 EC 08                                sub     esp, 8
.text:10070890 D9 55 FC                                fst     [ebp+frametime]
.text:10070893 DD 1C 24                                fstp    [esp+10h+var_10]
.text:10070896 E8 55 D5 0C 00                          call    ?GetClientVoiceMgr@@YAPAVCVoiceStatus@@XZ ; GetClientVoiceMgr(void)
.text:1007089B 8B C8                                   mov     this, eax       ; this
.text:1007089D E8 DE CF 0C 00                          call    ?Frame@CVoiceStatus@@QAEXN@Z ; CVoiceStatus::Frame(double)






Sedaj pa k problemu oz. moji želji. Rad bi nekak prišel do naslova na katerega kaže gpGlobals kazalec brez da bi vmt hook-al Init ali HudUpdate funkcijo. Na kakšen način bi dobil pointer ven iz mov inštrukcije. Naslov globalnega objekta razreda CHCClient mi je znan.
  • spremenilo: Klobasa ()

sas084 ::

Jst se sicer nisem nikoli ukvarjal z vmt hooking-om, vendar se mi zdi v tem primeru še najboljš varjanta.
Jst bi na tvojem mestu v IDI pogledu vse možne reference na pGlobals, možno je da se gpGlobals inicializira na fiksnem naslovu. Drugač pa ti verjetno ostane vmt, al pa če greš spreminjat runtime kodo.
V tem primeru maš lahko v funkciji HudUpdate() na naslovu 10070889 spremeniš fld ukaz v call/jmp ukaz, ki
preusmeri izvajanje v tvojo dll datoteko, kjer prebereš vsebino registra eax in popravš nazaj call/jmp na
fld ukaz. Isto bi se verjetno dalo z nastavitvijo SEH-a ter patchanje 10070889 naslova na vrednost 0xCC (software breakpoint), za slednje nism siguren no.

Klobasa ::

Najlepša hvala za odgovor, po parih dneh sem bil že kar malo skeptičen, da bo do kakega odgovora sploh prišlo.

Hm, da bi kakorkoli spreminjal runtime kodo dvomim iz dveh razlogov:
- prvi razlog je ta, da sem v IDI čisti začetnik ( nisem niti na dvestoti strani knjige ) in so mi te zadeve še velika neznanka.
- drugi razlog je pa ta, da ne vem, kako bi se na spreminjanje odzval Valve anti cheat software ( ob tej priložnosti bi rad samo dodal, da nisem nek nemoralen gamer, ki bi se izživljal nad noob-i na nekem random public serverju. Namen cheat-a je igranje na cheat vs. cheat serverjih in jaz ga jemljem kot učni pripomoček programiranja ).


Dobro bi bilo, da povem, zakaj mi je ta gpGlobals pointer tako pomemben. Preko tega pointerja pridem do spremenljivk kot sta recimo "maxclients" ( število klientov konektanih na server ) in pa "curtime" ( game current time ). Dve zelo pomembni zadevi.


Zaenkrat sem prišel do dveh rešitev, vsaka ima svojo slabost:
- Rešitev #1 je ta, da vmt hook-am Init funkcijo in poberem naslov iz argumenta. Slabost pri tem je ta, da ne morem inject-at dll-a naknadno, ko je igra že v teku. Prav tako ne morem uporabit hook-unhook med tem, ko je igra v teku z namenom, da bi naredil spremembe v kodi cheat-a in ponovno hook-al brez, da bi ponovno zagnal igro.
- Rešitev #2 je ta, da 1x hook-am Init funkcijo in logiram naslov objekta iz argumenta, potem pa s pomočjo tega naslova ustvarim offset ( (DWORD)EngineModuleHandle + offset = gpGlobals ). Slabost te metode je ta, da sem skoraj 100%, da se bo offset spremenil ob naslednjem update-u igre, ko bo engine.dll ponovno skompajlan.
- Rešitev #3, vem, da obstaja, vendar mi je trenutno še neznanka. Rešitev naj bi bila v deferenciranju in ne v derefenciranju, to naj bi bile dve različni zadevi. Gre pa nekako takole:

CSS::m_pGlobals = **( CGlobalVarsBase*** )((*( DWORD** )CSS::m_pClient)[11] + 0x2);

to je primer pridobivanja pointerja iz HudUpdate funkcije, ki je deloval par let nazaj, a ne deluje več ker ga jaz z mojim low asm znanjem ne znam prilagodit trenutnim razmeram.


Če se komu kaj sanja mu bom res hvaležen za kakršno koli pomoč.

Senitel ::

Preberi si tole.

Klobasa ::

Uh, hvala za zelo koristen link. Ni druge kot, da ostanem na rešitvi #2.


Vredno ogleda ...

TemaSporočilaOglediZadnje sporočilo
TemaSporočilaOglediZadnje sporočilo
»

[ASM] Pomoč, ne najdem napake

Oddelek: Programiranje
51105 (981) c0dehunter
»

asm - vnos stevilk s tipkovnice

Oddelek: Programiranje
51289 (1145) scarymovie
»

[nasm] scanf

Oddelek: Programiranje
272907 (2634) Brane2
»

[NALOGA][NASM] problem pri povezovanju s C-jevskimi funkcijami

Oddelek: Programiranje
61387 (1245) c00L3r
»

Zelo enostavna PHP skripta, ki ne dela - help :(

Oddelek: Izdelava spletišč
131573 (1338) snow

Več podobnih tem