-
Write two NOPs (0x90, 0x90) to 0x4D1C17 to be able to view officer notes regardless of guild rank.
-
Contributor
How easy would it be in C++ to read my target's HP and set it to a variable that an addon like MobHealth could then read from? Instead of having to damage the mob and get some sort of estimated health.
e: Reading health would be easy if I could find the right pointers (yes I've read the thread), but I'm not sure how I would go about the second part. Would making a variable initialized to some random preset number and scanning for it be a good way to go about it?
Maybe I'm over thinking it right now, tired.
Last edited by Valmere; 01-27-2016 at 07:50 AM.
-
Elite User
Originally Posted by
Valmere
How easy would it be in C++ to read my target's HP and set it to a variable that an addon like MobHealth could then read from? Instead of having to damage the mob and get some sort of estimated health.
e: Reading health would be easy if I could find the right pointers (yes I've read the thread), but I'm not sure how I would go about the second part. Would making a variable initialized to some random preset number and scanning for it be a good way to go about it?
Maybe I'm over thinking it right now, tired.
How about just using UnitHealth("target") which is a non-protected Lua function?
-
Originally Posted by
Valmere
How easy would it be in C++ to read my target's HP and set it to a variable that an addon like MobHealth could then read from? Instead of having to damage the mob and get some sort of estimated health.
e: Reading health would be easy if I could find the right pointers (yes I've read the thread), but I'm not sure how I would go about the second part. Would making a variable initialized to some random preset number and scanning for it be a good way to go about it?
Maybe I'm over thinking it right now, tired.
If you mean as a way of bypassing the health percentage displayed in-game and instead display the literal health value, that is not possible. The client is unaware of the actual health value, only the percentage. The only way to approximate it is to do some damage and see how much percentage it lost, which you've said you don't want to do. This is my understanding at least.
-
Contributor
Thanks for the replies. I assumed it was possible due to the screenshot in daCoder's program (Open Souce Project for WoW 1.12.1). After testing that out and trying the Lua function which returns 100 on anything but the player, my last idea will be to pull the data straight from a 1.12 database and hope Nost isn't very different.
Edit: Due to the database using level ranges and health multipliers I'm not able to make a full rip at first glance, but did manage to grab a fair amount of mobs. If anyone's using a fresh/blank MobHealth3 on Nost and wants some initial data, plop this into your SavedVariables folder.
Edit 2: Shame that most offsets in this thread are checked by Nost's "anti-cheat". Leveling is so tedious on vanilla
Last edited by Valmere; 01-28-2016 at 09:29 AM.
-
Member
Doesn't xperl display the health value in vanilla?
-
Originally Posted by
prospectingemu
Doesn't xperl display the health value in vanilla?
Not if the client is unaware of the value, which is a decision the server makes.
-
Post Thanks / Like - 1 Thanks
tutrakan (1 members gave Thanks to namreeb for this useful post)
-
Member
PlayerIsIndoor = base + 0x468608. 12.1 have m2Model__IsOutdoors?
-
Active Member
If you're using Cheat Engine to find these, I found it easier to do an AoB scan to find the non-static player coordinates. Kronos will insta-ban if you modify these too far out.
player x
?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 42 ?? ?? ?? ??
?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 3F
78 ?? ?? ?? ?? ?? ?? ?? 00 00 00 00 00 00 00 00
00 00 00 00
player y
?? ?? ?? ?? ?? ?? ?? 42 ?? ?? ?? ?? ?? ?? ?? ??
?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 3F 78 ?? ?? ??
?? ?? ?? ?? 00 00 00 00 00 00 00 00 00 00 00 00
player z
?? ?? ?? 42 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ??
?? ?? ?? ?? ?? ?? ?? 3F 78 ?? ?? ?? ?? ?? ?? ??
00 00 00 00 00 00 00 00 00 00 00 00
If you want to write a script, press CTRL+M and open Tools > Auto Assemble and type in...
[ENABLE]
aobscan(PLAYER_Y,?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 42 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 3F 78 ?? ?? ?? ?? ?? ?? ?? 00 00 00 00 00 00 00 00 00 00 00 00)
label(_playery)
registersymbol(_playery)
PLAYER_Y:
_playery:
[DISABLE]
unregistersymbol(_playery)
Then press File > Assign to current cheat table. Close the script window and go back to your cheat table and click on the checkmark box to activate the script. Now press "Add address manually" and type in _playery and switch it to float. Now you have the player Y non-static coordinates.
If you want to get player X and Player Z coordinates just add an offset to the pointer. So, press the "Add address manually" button and type in....
and to get player z...
Last edited by erfg12; 04-22-2016 at 05:45 AM.
-
Contributor
Updated fascall from c#
Originally Posted by
namreeb
My code to call __fastcall from C#:
Code:
static class FastCall
{
public static T CreateToFastcall<T>(IntPtr functionPtr, string patchName) where T : class
{
var method = typeof(T).GetMethod("Invoke");
if (method.GetParameters().Any(param => Marshal.SizeOf(param.ParameterType) != 4))
throw new ArgumentException("Only supports functions with 32 bit parameters");
var parameterCount = method.GetParameters().Length;
var payload = new List<byte>();
payload.Add(0x55); // push ebp
payload.AddRange(new byte[] { 0x89, 0xE5 }); // mov ebp, esp
payload.AddRange(new byte[] { 0x8B, 0x4D, 0x08 }); // mov ecx, [ebp+0x08]
payload.AddRange(new byte[] { 0x8B, 0x55, 0x0C }); // mov edx, [ebp+0x0C]
if (parameterCount > 2)
for (var i = 0; i < parameterCount - 2; i++)
{
payload.AddRange(new byte[] { 0x8B, 0x5D, (byte)(0x10 + 4*i) }); // mov ebx, [ebp+0x10+4*i]
payload.Add(0x53); // push ebx
}
var callOpcodeLocation = payload.Count + 1;
payload.AddRange(new byte[] { 0xE8, 0x00, 0x00, 0x00, 0x00 }); // call function
if (parameterCount > 2)
{
payload.AddRange(new byte[] {0x89, 0xEC }); // mov esp, ebp
payload.Add(0x5D); // pop ebp
}
payload.Add(0xC2);
payload.AddRange(BitConverter.GetBytes((ushort)(parameterCount * 4))); // retn 4 * paramCount
var payloadPtr = Locator.PayloadSpace(payload.Count);
var functionCall = functionPtr.ToInt32() - payloadPtr.ToInt32() - callOpcodeLocation - 5;
// update payload
payload[callOpcodeLocation + 0] = (byte)functionCall;
payload[callOpcodeLocation + 1] = (byte)(functionCall >> 8);
payload[callOpcodeLocation + 2] = (byte)(functionCall >> 16);
payload[callOpcodeLocation + 3] = (byte)(functionCall >> 24);
// deposit payload
Patcher.CreatePatch(new Patcher.Patch(payloadPtr, payload.ToArray(), patchName));
return Utilities.RegisterDelegate<T>(payloadPtr);
}
public static void RemoveToFastcall(string patchName)
{
Patcher.RemovePatch(patchName);
}
}
Thank you a lot Namreeb! Let me re post it with some corrections:
Code:
static class FastCall
{
public static T CreateToFastcall<T>(IntPtr functionPtr, string patchName) where T : class
{
var method = typeof(T).GetMethod("Invoke");
// if (method.GetParameters().Any(param => Marshal.SizeOf(param.ParameterType) != 4))
// throw new ArgumentException("Only supports functions with 32 bit parameters");
var parameterCount = method.GetParameters().Length;
var payload = new List<byte>();
payload.Add(0x55); // push ebp
payload.AddRange(new byte[] { 0x89, 0xE5 }); // mov ebp, esp
payload.Add(0x53); // push ebx
payload.AddRange(new byte[] { 0x8B, 0x4D, 0x08 }); // mov ecx, [ebp+0x08]
payload.AddRange(new byte[] { 0x8B, 0x55, 0x0C }); // mov edx, [ebp+0x0C]
if (parameterCount > 2)
{
int paramsToPush = parameterCount - 2; // always > 0
for (var i = 0; i < paramsToPush; i++)
{
payload.AddRange(new byte[] { 0x8B, 0x5D, (byte)(0x10 + 4 * (paramsToPush - 1 - i)) }); // mov ebx, [ebp+0x10+4*(paramToPush-1-i)]
payload.Add(0x53); // push ebx
}
}
var callOpcodeLocation = payload.Count + 1;
payload.AddRange(new byte[] { 0xE8, 0x00, 0x00, 0x00, 0x00 }); // call function
payload.Add(0x5B); // pop ebx
payload.AddRange(new byte[] { 0x89, 0xEC }); // mov esp, ebp
payload.Add(0x5D); // pop ebp
payload.Add(0xC2);
payload.AddRange(BitConverter.GetBytes((ushort)(parameterCount * 4))); // retn 4 * paramCount
var payloadPtr = Locator.PayloadSpace(payload.Count);
var functionCall = functionPtr.ToInt32() - payloadPtr.ToInt32() - callOpcodeLocation - 4;
// update payload
payload[callOpcodeLocation + 0] = (byte)functionCall;
payload[callOpcodeLocation + 1] = (byte)(functionCall >> 8);
payload[callOpcodeLocation + 2] = (byte)(functionCall >> 16);
payload[callOpcodeLocation + 3] = (byte)(functionCall >> 24);
// deposit payload
Patcher.CreatePatch(new Patcher.Patch(payloadPtr, payload.ToArray(), patchName));
return Utilities.RegisterDelegate<T>(payloadPtr);
}
public static void RemoveToFastcall(string patchName)
{
Patcher.RemovePatch(patchName);
}
}
P.S I Would like someone of you guys pm me with the idb ida file for wow 1.12.1. Thanks.
Update - lesser but more readable code (Ironically, isn't often the case?):
Code:
internal static class Fastcall
{
public static List<IntPtr> FastCallWrappers;
//Is important to pass at least two params and know that the first two parameters are ALWAYS 32bit
public static T StdcallToFastcall<T>(IntPtr functionPtr) where T : class
{
var wrapper = new List<byte>();
wrapper.Add(0x58); // pop eax - store the return address
wrapper.Add(0x59); // pop ecx - move the 1st argument to ecx
wrapper.Add(0x5A); // pop edx - move the 2nd argument to edx
wrapper.Add(0x50); // push eax - restore the return address
wrapper.Add(0x68); // push ...
wrapper.AddRange(BitConverter.GetBytes(functionPtr.ToInt32())); // the function address to call
wrapper.Add(0xC3); // ret - and jump to
var wrapperPtr = Marshal.AllocHGlobal(wrapper.Count);
Marshal.Copy(wrapper.ToArray(), 0, wrapperPtr, wrapper.Count);
if (FastCallWrappers == null)
FastCallWrappers = new List<IntPtr>();
FastCallWrappers.Add(wrapperPtr);
return Marshal.GetDelegateForFunctionPointer<T>(wrapperPtr);
}
public static void RemoveFastcalls()
{
if (FastCallWrappers == null)
return;
foreach (var p in FastCallWrappers)
Marshal.FreeHGlobal(p);
}
}
Last edited by tutrakan; 12-24-2017 at 12:03 AM.
-
Contributor
Hi, i have two questions so far and i ...
1_st: Solved:
Code:
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate short IsSpellInRangeDelegate(uint localPlayerAddr, ref SpellEntry spellRec, ulong guid, int doSomeSpellChecks = 0);
_isSpellInRange = Fastcall.CreateToFastcall<IsSpellInRangeDelegate>((IntPtr)0x006E4440, "IsSpellInRange"
2_nd: Solved too. I received LuaType 5 - table instead of string because of wrong indexing.
Code:
default:
return "<unknown lua type>";
public enum LuaConstant
{
MultRet = -1,
TypeNil = 0,
TypeBoolean = 1,
TypeNumber = 3,
TypeString = 4,
}
P.S Some stuff:
Code:
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate bool IsUsableSpellDelegate(ref SpellEntry spellRec, ref bool notEnoughPower);
_isUsableSpell = Fastcall.CreateToFastcall<IsUsableSpellDelegate>((IntPtr)0x006E3D60, "IsUsableSpell");
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
private delegate bool CanAttackDelegate(uint unit, uint otherUnit);
_canAttack = Marshal.GetDelegateForFunctionPointer<CanAttackDelegate>((IntPtr)0x00606980);
public bool CastPacket(Unit unit)
{
var mask = unit == Manager.Me ? SpellCastTargetFlags.TARGET_FLAG_SELF : SpellCastTargetFlags.TARGET_FLAG_UNIT;
var packet = new DataStore(NetMessage.CMSG_CAST_SPELL);
packet.Write<int>((int)Id);
packet.Write<short>((Int16)mask);
WriteGuid(ref packet, unit.Guid);
packet.Send();
return true;
}
public static void WriteGuid(ref DataStore cds, ulong guid)
{
var packGUID = new List<byte>();
packGUID.Add(0);
ulong g = guid;
for (int i = 0; g != 0; ++i)
{
if ((g & 0xFF) != 0)
{
packGUID[0] |= (byte)(1 << i);
packGUID.Add((byte)(g & 0xFF));
}
g >>= 8;
}
foreach (byte b in packGUID)
{
cds.Write<byte>(b);
}
}
Thanks!
Last edited by tutrakan; 11-13-2016 at 12:32 PM.
-
Originally Posted by
tutrakan
2_nd: Why i get in my queries luatype == 5 when the enum is up to 4:
Sorry I can't help you with the first question (only ever did some simple hacks on vanilla) but this is an easy one.
Code:
#define LUA_MULTRET (-1)
#define LUA_TNIL 0
#define LUA_TBOOLEAN 1
#define LUA_TLIGHTUSERDATA 2
#define LUA_TNUMBER 3
#define LUA_TSTRING 4
#define LUA_TTABLE 5
#define LUA_TFUNCTION 6
#define LUA_TUSERDATA 7
#define LUA_TTHREAD 8
5 indicates a table. Reading the values from the table wouldn't be too hard, but assuming you're using the typical loadbuffer approach you're probably much better off formatting the Lua code to return as multiple stack objects rather than a single table object.
Example - rather than executing:
Code:
return func_that_returns_table()
You could instead execute this:
Code:
result = func_that_returns_table(); return result.foo, result.bar
Last edited by Jadd; 05-06-2016 at 12:36 AM.
-
Post Thanks / Like - 1 Thanks
tutrakan (1 members gave Thanks to Jadd for this useful post)
-
Member
Code:
ChanellingSpellId = (0x0084E4BC) + 0x24) + 0xec) + 0x228
Does someone please have ObjectFields.OBJECT_END ? Sacred dumped the descriptors, but forgot to include ObjectFields...
-
Originally Posted by
wowwac
Code:
ChanellingSpellId = (0x0084E4BC) + 0x24) + 0xec) + 0x228
Does someone please have ObjectFields.OBJECT_END ? Sacred dumped the descriptors, but forgot to include ObjectFields...
Code:
OBJECT_FIELD_GUID = 0,
OBJECT_FIELD_TYPE = 2,
OBJECT_FIELD_ENTRY = 3,
OBJECT_FIELD_SCALE_X = 4,
OBJECT_FIELD_PADDING = 5,
OBJECT_FIELD_END = 6
Keep in mind these are not already multiplied by 4 whereas Sacred's are. OBJECT_FIELD_END = 0x18 is probably what you're looking for.
-
Post Thanks / Like - 1 Thanks
wowwac (1 members gave Thanks to Jadd for this useful post)
-
Member
Thank you, that's what I was looking for...