usagiuke / BolterV2

3 stars 1 forks source link

Quick question #1

Open cacodemonx opened 10 years ago

cacodemonx commented 10 years ago

Hi, I have been following this project for a while while trying to code a similar thing in C++ for training purposes. I got the movement block (asm) thing working just fine but the pointer I get for MasterPointer seems correct but it has no valid data inside once I cast it to a struct. The target is null and player struct seem's to contain all bogus data. I am just wondering if the code is even correct as of now? The sigPoints[8] + 0x30 thing is the weird thing to me. Sorry if I posted in wrong place, I can't seem to send you a pm anywhere.

//ASM Pos Changers ReadProcessMemory(Hook.ProcessHandle, (LPCVOID)(sigPoints[3] + 36), (LPVOID)&ServerPosStruct, sizeof(ServerPosAsm), 0); //Function that modifies pos NOP it! ReadProcessMemory(Hook.ProcessHandle, (LPCVOID)(sigPoints[2] + 11), (LPVOID)&ClientPosStruct, sizeof(ClientPosAsm), 0); //Function that modifies pos NOP it! memcpy(&OriginalServerPosStruct, &ServerPosStruct, sizeof(ServerPosAsm)); //Backup the original code memcpy(&OriginalClientPosStruct, &ClientPosStruct, sizeof(ClientPosAsm)); //Backup the original code //

    //Game master struct
    DWORD MasterPtr = 0;
    ReadProcessMemory(Hook.ProcessHandle, (LPCVOID)(sigPoints[8] + 0x30), (LPVOID)&MasterPtr, sizeof(DWORD), 0);
    ReadProcessMemory(Hook.ProcessHandle, (LPCVOID)MasterPtr, (LPVOID)&GameStruct, sizeof(MasterPointer), 0);
    //
usagiuke commented 10 years ago

this is a direct translation from C# to C++

(Switch memcpy() to appropriate calls if remote)

http://www.privatepaste.com/63b204048a

ShowName() will display your character's name (the first entity)

cacodemonx commented 10 years ago

Thanks a lot! I got it working, it seems I did forget the struct alignment after all, kinda silly of me.

Just one last question, do you know where the camera stuff is stored? like the pitch, yaw etc? I want to try make a function where it simply takes you forward or even up depending on where you are looking. From what I saw bolter does not seem to have that kindof feature yet.

usagiuke commented 10 years ago

I haven't disassembled the cam stuff yet, I have found the location, just haven't decoded the structures. There are some cam adjustment functions in the Entity and Entity->subStruct, that move the cam, mostly up and down though.

usagiuke commented 10 years ago

For further inquiries, email here http://address-protector.com/5IvCCCijPea3dCida12ntYmrqfa2W3GNKRiEGLu2aMq3XMu-rq3fD9BzdzQhkNO9

usagiuke commented 10 years ago

Reopened because github doesn't have PMs. the camera structure pointer is the first member in the target struct. (now should be called the player info?) Still decoding it, but here is the full structure (in C#)

    public struct Camera
    {
        private fixed byte Unknown0[0x40];
        public float UnknownCam0; //offset 0x40
        public float UnknownCam1; //offset 0x44
        public float UnknownCam2; //offset 0x48
        private fixed byte Unknown3[0x24];
        public float UnknownCam3; //offset 0x70
        public float UnknownCam4; //offset 0x74
        public float UnknownCam5; //offset 0x78
        private fixed byte Unknown6[0x4];
        public float UnknownCam6; //offset 0x80
        public float UnknownCam7; //offset 0x84
        public float UnknownCam8; //offset 0x88
        private fixed byte Unknown9[0x4];
        public float UnknownCam9; //offset 0x90
        public float UnknownCam10; //offset 0x94
        public float UnknownCam11; //offset 0x98
        private fixed byte Unknown12[0x8];
        public float UnknownCam12; //offset 0xA4
        public float UnknownCam13; //offset 0xA8
        private fixed byte Unknown14[0x4];
        public float UnknownCam14; //offset 0xB0
        public float UnknownCam15; //offset 0xB4
        public float UnknownCam16; //offset 0xB8
        private fixed byte Unknown17[0x4];
        public float UnknownCam17; //offset 0xC0
        public float UnknownCam18; //offset 0xC4
        public float UnknownCam19; //offset 0xC8
        private fixed byte Unknown20[0x1C];
        public float Zoom; //offset 0xE8
        private fixed byte Unknown21[0x14];
        public float UnknownCam21; //offset 0x100
        public float UnknownCam22; //offset 0x104
        private fixed byte Unknown23[0x38];
        public float Zoom2; //offset 0x140
        private fixed byte Unknown24[0x1C];
        public float UnknownCam24; //offset 0x160
        public float UnknownCam25; //offset 0x164
        public float UnknownCam26; //offset 0x168
        private fixed byte Unknown27[0x4];
        public float UnknownCam27; //offset 0x170
        public float UnknownCam28; //offset 0x174
        public float UnknownCam29; //offset 0x178
        private fixed byte Unknown30[0x4];
        public float UnknownCam30; //offset 0x180
        public float UnknownCam31; //offset 0x184
        public float UnknownCam32; //offset 0x188
        private fixed byte Unknown33[0x44];
        public float UnknownCam33; //offset 0x1D0
        public float UnknownCam34; //offset 0x1D4
        public float UnknownCam35; //offset 0x1D8
        private fixed byte Unknown36[0xC];
        public float UnknownCam36; //offset 0x1E8
        private fixed byte Unknown37[0x44];
        public float UnknownCam37; //offset 0x230
        public float UnknownCam38; //offset 0x234
        public float UnknownCam39; //offset 0x238

    }
cacodemonx commented 10 years ago

Thanks! how are you finding these structs so quickly? I want to learn! my ida skills are not very good. Also the masterptr player and subplayer structs have changed in last patch? I forgot to write down the previous values and not struggling to update the structs :(

usagiuke commented 10 years ago

I'll commit the fixed version, the sig for MasterPtr only had one byte changed, and the structure shifted 12 bytes. playerstruct got changed around a lot. Making some major changes to the code, so pls excuse the layout lol. but GameStructs.h has the new structure layouts in C/C++.

cacodemonx commented 10 years ago

Ahh awsome! thanks a lot for updating it, it all now works again. I am really curious as how you get those structs so precise, I always struggle with things like that, is there some trick to it or just lots and lots of analysis?

usagiuke commented 10 years ago

Mixture of both, it depends on how much I already know about the structure. To find them from scratch, I use a combination of IDA and CE, CE I use for finding a value that may be in the structure, and then with IDA, I find the function writing to that member, and walk the routine call path backwards, until I discover where the pointer is being created. once I find the pointer, I take an assumed size based on allocation of that memory block, and begin analysis on each member (varies greatly on what I'm looking for), I then pull all the members of interest into CE's address table, and save it. I use a C# app to convert the .CT file into a structure, adds the unknown spacers and formatting etc.

generally I name the members of interest appropriately, but I haven't worked with cam stuff much. so I didn't want to give the members inappropriate names, I do know XIV lays axes out X,Z,Y. so that should help me out some.

cacodemonx commented 10 years ago

Thanks I will start reading up on it, Have you any idea where the health values are in the PCMobStruct? and any idea where the skillbar data is located with skill info?

usagiuke commented 10 years ago

HP/MP etc was at 16A0 before the update. they have shifted, but I can't recall the new offsets, I'll get back to you when I have time to look over it. The values are stored exactly how they are shown, so you could use CE to find the changing values, and scan for your exact HP, then change classes/gear etc, and rescan with your new HP. (using max HP is probably best, to not get messed up by regen)

cacodemonx commented 10 years ago

I managed to get flying to work but because the ASM movement block thing the other entities are not updated either, like the other players and enemies, is there any way to just block my movement while allowing the other entities?

usagiuke commented 10 years ago

you would have to hook the entire movement block, and add a cmp, to the register that holds your character's entity pointer

ex. If eax stores the entity pointer

     cmp eax,[your entity] //compare your entity pointer against the current iteration
v----je // redirect flow to nops, if the above is true.
v    (update X) // these fire if the above cmp was false
v    (update Z)
v    (update Y)
v-->nop
usagiuke commented 10 years ago

flying seems cool, so, I'll write the hook for you when I get time, if you don't before hand.

cacodemonx commented 10 years ago

Ah thanks that would be great, I still have not implemented that hook, kinda getting advanced for me.

For my flying control this works good:

    float Scale  = 0.0f;
    float Up     = 0.0f;

    if(KEYDOWN(0x57) || (KEYDOWN(VK_LBUTTON) && KEYDOWN(VK_RBUTTON)))Scale =  0.05f * Delta; //W
    if(KEYDOWN(0x53))Scale = -0.05f * Delta; //S

    if(KEYDOWN(VK_SPACE))Up   =  0.05f * Delta; //Space
    if(KEYDOWN(VK_CONTROL))Up = -0.05f * Delta; //Control

    float Heading = Entities[0].Heading;

    Entities[0].ServerPos.x += Scale * sinf(Heading);
    Entities[0].ServerPos.z += Up;
    Entities[0].ServerPos.y += Scale * cosf(Heading);
usagiuke commented 10 years ago

http://www.privatepaste.com/0d9f035a53 this is the movement interception. I have example calls at the top, (sorry for the casting galore, wrote this quickly). but the MovementIntercept struct lays out what is all going on.

cacodemonx commented 10 years ago

wow thanks a lot! will implement this asap and let you know.

usagiuke commented 10 years ago

It's going to need a bit of working, if you're doing things with WPM/RPM i.e

jmp dword ptr [CliMovePtr]

CliMovePtr is a pointer to the location in executable memory to go back to, to give the game back control. and since this means effectively, it's a pointer of a pointer. it needs to be allocated locally. you can append it to the Initialization VirtualAlloc(Ex)() if you'd like.

cacodemonx commented 10 years ago

I am kinda struggling with this concept, since I am using an external method I had to change some things, can you tell me if I am on the right track?

// pCliMov: Pointer to the instruction at the beginning of the CliMovmentAsm
// pServMov:  Pointer to the instruction at the beginning of the ServMovmentAsm
// pEntity: Pointer to your characters entity (also the beginning of the PC/Mob Entities)
void AllocateASMMemory(DWORD ClientASMFirstInstruction, DWORD ServerASMFirstInstruction, DWORD PlayerEntityPtr)
{
    //Allocate a memory block for the ASM
    DWORD CustomASMStart = (DWORD)VirtualAllocEx(Hook.ProcessHandle, 0, sizeof(MoveIntercept), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); //Allocate some memory in the process
    WriteProcessMemory(Hook.ProcessHandle, (LPVOID)CustomASMStart, InterceptASMBytes, sizeof(MoveIntercept), 0); //Write to that memory our custom ASM bytes
    //

    //Fill in custom ASM variables
    WriteProcessMemory(Hook.ProcessHandle, (LPVOID)(CustomASMStart + offsetof(MoveIntercept, EntityPtr)),  &PlayerEntityPtr, sizeof(DWORD), 0);
    WriteProcessMemory(Hook.ProcessHandle, (LPVOID)(CustomASMStart + offsetof(MoveIntercept, EntityPtr2)), &PlayerEntityPtr, sizeof(DWORD), 0);

    WriteProcessMemory(Hook.ProcessHandle, (LPVOID)(CustomASMStart + offsetof(MoveIntercept, CXFunc)), ClientBytesX, 5, 0);
    WriteProcessMemory(Hook.ProcessHandle, (LPVOID)(CustomASMStart + offsetof(MoveIntercept, CZFunc)), ClientBytesZ, 5, 0);
    WriteProcessMemory(Hook.ProcessHandle, (LPVOID)(CustomASMStart + offsetof(MoveIntercept, CYFunc)), ClientBytesY, 5, 0);
    WriteProcessMemory(Hook.ProcessHandle, (LPVOID)(CustomASMStart + offsetof(MoveIntercept, CXFunc2)), Null5, 5, 0);
    WriteProcessMemory(Hook.ProcessHandle, (LPVOID)(CustomASMStart + offsetof(MoveIntercept, CZFunc2)), Null5, 5, 0);
    WriteProcessMemory(Hook.ProcessHandle, (LPVOID)(CustomASMStart + offsetof(MoveIntercept, CYFunc2)), Null5, 5, 0);

    WriteProcessMemory(Hook.ProcessHandle, (LPVOID)(CustomASMStart + offsetof(MoveIntercept, SXFunc)), ServerBytesX, 8, 0);
    WriteProcessMemory(Hook.ProcessHandle, (LPVOID)(CustomASMStart + offsetof(MoveIntercept, SZFunc)), ServerBytesZ, 8, 0);
    WriteProcessMemory(Hook.ProcessHandle, (LPVOID)(CustomASMStart + offsetof(MoveIntercept, SYFunc)), ServerBytesY, 8, 0);
    WriteProcessMemory(Hook.ProcessHandle, (LPVOID)(CustomASMStart + offsetof(MoveIntercept, SXFunc2)), Null8, 8, 0);
    WriteProcessMemory(Hook.ProcessHandle, (LPVOID)(CustomASMStart + offsetof(MoveIntercept, SZFunc2)), Null8, 8, 0);
    WriteProcessMemory(Hook.ProcessHandle, (LPVOID)(CustomASMStart + offsetof(MoveIntercept, SYFunc2)), Null8, 8, 0);
    //
}

As fas as I understand this allocates a memory block anywhere in the process and then I have to modify the game's asm to go to my new code block? How do I allocate the jmp dword ptr [CliMovePtr] stuff?

Thanks

usagiuke commented 10 years ago

http://www.privatepaste.com/9d0f48e5c2 CliMovePtr needs to point to the instruction that comes right after all the movss, in the original game asm. (same for ServMovePtr) The above paste adds some comments, and shows you can use the end of the MoveIntercept struct, to hold those pointers.

this part CliMovementPtr = pCliMov + 30; ServMovementPtr = pServMov + 39;

is me getting the addresses of the instruction that comes right after all the movss

usagiuke commented 10 years ago

Just to clarify, on this question ~"As fas as I understand this allocates a memory block anywhere in the process and then I have to modify the game's asm to go to my new code block? "~ Yes once the asm is allocated. the jmpptr/2 will be written at the top of the original game movss's and from there on, every movement update will be redirected to your custom asm. which now has full control of who should not get an update.

usagiuke commented 10 years ago

If you are still having trouble, someone suggested something to me, that may make it easier on you. you can use the "naked" keyword, to write asm out in c++. DWORD nulljmpptr = INFINITE; http://www.privatepaste.com/f94148a2fd

some of the offsets are off,you can verify them against the game's movement.

but basically, VirtualAllocEX sizeof(The entire asm) + 14 copy naked asm over. WriteProccessMemory to (base of asm + sizeof(The entire asm)), the address we need to return to for client movement. WriteProccessMemory to (base of asm + sizeof(The entire asm) + 4), the address we need to return to for server movement .WriteProccessMemory to (base of asm + sizeof(The entire asm) + 8), the address to our client entity cmp instruction. WriteProccessMemory to (base of asm + sizeof(The entire asm) + 12), the address to our server entity cmp instruction. WriteProccessMemory: turn both "7FFFFFEh" into our entity. WriteProccessMemory: turn the first "nulljmpptr" into (base of asm + sizeof(The entire asm)) WriteProccessMemory: turn the second "nulljmpptr" into (base of asm + sizeof(The entire asm) + 4) This is how it looks in memory (before writes). http://i842.photobucket.com/albums/zz348/usagiuke/memass_zpsb9915fb5.png

the jmp DWORD PTR nulljmpptr make two of those, and change nulljmpptr to (base of asm + sizeof(The entire asm) + 8) 1st (base of asm + sizeof(The entire asm) + 12) 2nd

.WriteProccessMemory to Top of client game movement, our jmp DWORD PTR (base of asm + sizeof(The entire asm) + 8) .WriteProccessMemory to Top of server game movement, our jmp DWORD PTR (base of asm + sizeof(The entire asm) + 12)

if all done correctly, the game should be hopping to our custom assembly, then hopping back when done.

cacodemonx commented 10 years ago

Ah very cool, you say to VirtualAllocEX sizeof(The entire asm) + 14, how can I get the size of a naked function? or do you count the bytes manually?

cacodemonx commented 10 years ago

Also how can I view my created assembly in cheat engine? VirtualAllocEx returns a dword but if I click memory view and go to that address there is a bunch of jmp commands, nothing resembling the asm that is defined in the naked function.

usagiuke commented 10 years ago

depending on the compiler flags. the naked asm will either be a jmp or the raw assembly. It sounds like you have the jump case. look at the &nakedasm in memory view. If it's a jmp, right click and press "follow" That will show the naked assembly. to get that address from your code. you will have to do something like this

DWORD jmpadrress = (DWORD)&NakedAsm;
DWORD jmpsize = *(DWORD*)(jmpadrress + 1)
LPVOID RawAsm = (LPVOID)(jmpadrress + jmpsize + 5);