Read Current/Max health without codecaves.

10/20/2008 05:47 high6#1
Made this in C# to show how to read the current and max health of your character without code caves.

Code:
static class HpReader
        {
            #region APIs
            [DllImport("kernel32.dll")]
            private static extern int OpenProcess(int dwDesiredAccess, int bInheritHandle, int dwProcessId);
            [DllImport("kernel32.dll")]
            private static extern int CloseHandle(int hObject);
            [DllImport("kernel32.dll")]
            private static extern int ReadProcessMemory(int hProcess, int lpBaseAddress, byte[] lpBuffer, int nSize, int lpNumberOfBytesWritten);
            #endregion

            #region consts
            const int PROCESS_ALL_ACCESS = 0x1F0FFF;
            const int BaseAddr = 0x0057B580;
            #endregion

            #region ReadX
            static int ReadInt(int handle, int addr)
            {
                byte[] buf = new byte[4];
                ReadProcessMemory(handle, addr, buf, 4, 0);
                return BitConverter.ToInt32(buf, 0);
            }
            static int ReadShort(int handle, int addr)
            {
                byte[] buf = new byte[2];
                ReadProcessMemory(handle, addr, buf, 2, 0);
                return BitConverter.ToInt16(buf, 0);
            }
            static byte ReadByte(int handle, int addr)
            {
                byte[] buf = new byte[1];
                ReadProcessMemory(handle, addr, buf, 1, 0);
                return buf[0];
            }
            #endregion

            #region ReadHp
            static int RotateLeft(int num, int shift)
            {
                shift = shift % 32;
                if (shift == 0)
                    return num;
                return (num << shift) | (num >> (32 - shift));
            }
            static int RotateRight(int num, int shift)
            {
                shift = shift % 32;
                if (shift == 0)
                    return num;
                return (num >> shift) | (num << (32 - shift));
            }
            static int sub_4ECE67(int h, int Base)
            {
                int ret = 1;
                int v2 = ReadInt(h, Base + 4);
                if (v2 != 0)
                {
                    ret = ReadInt(h, Base + 8);
                    if (v2 == 1)
                    {
                        ret -= 2;
                    }
                    else if (v2 == 2)
                    {
                        if ((ret & 1) == 0)
                            return 0;
                        ret = (ret >> 1) + 1;
                    }
                    else if (v2 == 3)
                    {
                        if ((ret & 1) == 1)
                            return 0;

                        if ((ret & 1) != 0)
                            ret = (ret >> 1) + 1;
                        else
                            ret >>= 1;
                    }
                }
                return ret;
            }
            static int sub_4ECF03(int h, int Base, int num, int shift)
            {
                int ret = 0;
                int v3 = ReadInt(h, Base + 4);
                if (v3 == 0 || v3 == 2)
                {
                    ret = RotateRight(num, shift);
                }
                else if (v3 == 1 || v3 == 3)
                {
                    ret = RotateLeft(num, shift);
                }
                else
                {
                    ret = v3;
                }
                return ret;
            }
            static int sub_4ECD10(int h, int Base)
            {
                int v3 = sub_4ECE67(h, Base);
                if (v3 < 0)
                    throw new Exception("Error1");
                if (ReadInt(h, Base + 12) == 0)
                    throw new Exception("Error2");
                return sub_4ECF03(h, Base, ReadInt(h, (ReadInt(h, Base + 12) + 4 * v3)), v3);
            }
            public static int ReadHp(Process p)
            {
                return ReadHp(p.Id);
            }
            public static int ReadHp(int id)
            {
                int h = OpenProcess(PROCESS_ALL_ACCESS, 0, id);
                if (h == 0)
                    throw new Exception("Could not open process!");

                int ret = 0;
                int NewBase = ReadInt(h,BaseAddr+3520);
                if (NewBase != 0)
                {
                    ret = sub_4ECD10(h, NewBase);
                }
                else
                {
                    throw new Exception("Error0");
                }

                CloseHandle(h);
                return ret;
            }
            #endregion

            #region ReadMaxHp
            public static int ReadMaxHp(Process p)
            {
                return ReadHp(p.Id);
            }
            public static int ReadMaxHp(int id)
            {
                int h = OpenProcess(PROCESS_ALL_ACCESS, 0, id);
                if (h == 0)
                    throw new Exception("Could not open process!");

                if (ReadInt(h, BaseAddr + 76) != 0)
                {
                    return ReadInt(h, BaseAddr + 2208);
                }
                int health = 3 * (ReadInt(h, BaseAddr + 2184) + ReadInt(h, BaseAddr + 2192) + ReadInt(h, BaseAddr + 2200) + 8 * ReadInt(h, BaseAddr + 2196));
                int v1 = ReadInt(h, BaseAddr + 2996);
                
                if (v1 % 0x3E8u / 0xA == 1)
                {   
                    int v5 = 0;
                    if (v1 % 0xAu == 1)
                    {
                        v5 = 5;
                    }
                    else if (v1 % 0xAu == 2)
                    {
                        v5 = 8;
                    }
                    else if (v1 % 0xAu == 3)
                    {
                        v5 = 10;

                    }
                    else if (v1 % 0xAu == 4)
                    {
                        v5 = 12;
                    }
                    else if (v1 % 0xAu == 5)
                    {
                        v5 = 15;
                    }
                    health += health * v5 / 100;
                }

                int addr = ReadInt(h,BaseAddr + 4228);
                for (int i = 0; i < 8; i++)
                {
                    if (ReadInt(h, addr) != 0)
                    {
                        if (ReadByte(h,addr + 372) == 0)
                        {
                            health += ReadInt(h, addr + 328) + ReadShort(h, addr + 86) + ReadShort(h, addr + 336);
                        }
                    }
                    addr += 4;
                }

                CloseHandle(h);
                return health;
            }
            #endregion
        }
Example use

Code:
Process[] ps = Process.GetProcessesByName("conquer");
            int health = HpReader.ReadHp(ps[0]);
10/20/2008 12:49 MushyPeas#2
Nice, pretty complex too for just storing a HP value :p
10/21/2008 04:41 iliveoncaffiene#3
The sub_XXXX naming makes me think he didn't code this completely on his own. (IDA?)
10/21/2008 05:56 operaopera#4
BaseAddr change if client update?
10/21/2008 20:30 high6#5
Quote:
Originally Posted by operaopera View Post
BaseAddr change if client update?
yes

Quote:
Originally Posted by iliveoncaffiene View Post
The sub_XXXX naming makes me think he didn't code this completely on his own. (IDA?)
I wrote it from the pseudo C from ida. I am terrible at naming stuff so I just left the method names.
10/21/2008 21:23 masteryoda1047#6
how do you find the right address?

i mean, like using cheatengine and search for text strings is not too difficult, but how to find integer values in the memory??

And could you put more comments in your code, f.ex. i don't see why you do a modulo 32 at the shift part.

thx
10/21/2008 21:38 high6#7
Quote:
Originally Posted by masteryoda1047 View Post
how do you find the right address?

i mean, like using cheatengine and search for text strings is not too difficult, but how to find integer values in the memory??

And could you put more comments in your code, f.ex. i don't see why you do a modulo 32 at the shift part.

thx
Comments aren't assembled into the exe. I really don't feel like spending time commenting every line.

the % 32 is because when you rotate the bits 32 times it is like you never rotated them. So I just had it keep it in the 32 bounds.
10/21/2008 22:31 teh_n00b#8
for some reason I get -5050 when i do this:

Process[] ps = Process.GetProcessesByName("conquer");
int health = HpReader.ReadHp(ps[0]);

label1.Text = health.ToString();

Can anyone help me `with why this happens?
10/21/2008 23:29 high6#9
Quote:
Originally Posted by teh_n00b View Post
for some reason I get -5050 when i do this:

Process[] ps = Process.GetProcessesByName("conquer");
int health = HpReader.ReadHp(ps[0]);

label1.Text = health.ToString();

Can anyone help me `with why this happens?
Not without more info.
10/22/2008 06:39 teh_n00b#10
Quote:
Originally Posted by high6 View Post
Not without more info.
Thats actually all there is in my code atm :)

well.. also a thread that makes the same result, but only those 3 lines, and then your code. :(

edit: hmm.. on my other comp. it seems to be working :S

edit2: disregard that ^^ reading maxHP doesnt seem to work here :(