|
thanks to all who help...
1)How do i read a 2 byte, 4 byte, or 8 byte value? I know how to read a one byte, but that only goes up to 255...
2)If any of you are familiar assembly, i need know now how to change (write) to an addresses hex dump, also known as Array of Byte (in most memory editing engines).
3) Reading/writing to a pointer I.E (0x1009624, offset: 0xb14), or any other pointer...
thanks in advanced
|
|
|
|
|
What does this relate to ? Where are you reading from ?
pointers are easy, you just create an unsafe block, and you can manipulate them, as if they are an array.
Christian Graus - Microsoft MVP - C++
"I am working on a project that will convert a FORTRAN code to corresponding C++ code.I am not aware of FORTRAN syntax" ( spotted in the C++/CLI forum )
|
|
|
|
|
1)
Code:
ProcessMemoryReaderLib.ProcessMemoryReader memedit = new ProcessMemoryReaderLib.ProcessMemoryReader();
memedit.ReadProcess = myprocess[0];
memedit.OpenProcess();
int bytesread; //needed
int byteswritten; //needed
int address = 0x1009624; //address
int value; //value of address
short value2=444; //for writing 2 byte, 444 for the value
byte[] memory; //for reading byte reading
memory = memedit.ReadProcessMemory((IntPtr)address, 1, out bytesread); //starts out as a byte array...i'm wondering how to get around this...
value = memory[0];
MessageBox.Show(value.ToString());
//writing memory =
BitConverter.GetBytes(value2);
memedit.WriteProcessMemory((IntPtr)address, memory, out byteswritten);
As you can see, when you read an address...the value is assigned to a byte array, how do I get around this? Like if I want to read a 4-byte value.
2) I need to be able to make a IntPtr pointer to an address with an offset, aka a pointer...should be simple but i can't figure it out...
3) I need to be able to edit or change the hex dump of an address, for example... lets say the hex dump of an address is 8f 00 00 00 ae 00 3f or something, i need to be able to change it to 8f 01 00 00 00 ae 00 3f. That's just an example...thanks in advance.
|
|
|
|
|
Hi,
1.
I am unfamiliar with ProcessMemoryReaderLib; if it only offers Read methods
that return byte[] then it is up to you to convert some bytes into other types
such as int. There are basically two ways to do this:
- algorithmically, writing some code that performs the necessary calculations
- thru a memory-based union (one of the tricks from good old Fortran days):
create a struct that contains both data types, and give it marshaling attributes
that make the members occupy the same memory addresses (FieldOffset).
The former requires you take care of big-endian/little-endian considerations,
the latter will apply your machine's endianness (LE for x86).
BTW if you want an array in your union, you must "flatten" it, by applying
additional attributes as in:
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public byte[] myArray;
otherwise the struct simply stores the array reference.
2.
You can convert an IntPtr to an int using one of its methods; then add to it,
and cast it back to an IntPtr.
3.
if by changing a hex dump you mean changing the memory content, it seems you
need some code to modify the byte[] you read, and then pass it back to the
appropriate Write method. Your target process may suffer !
|
|
|
|
|
OK GREAT! But i still don't understand 2 very well, could you elaborate a little?
|
|
|
|
|
Some variations are possible, e.g.
IntPtr myIntPtr2=new IntPtr(myIntPtr1.ToInt32()+myIntOffset);
BTW on Win64 you would have to use ToInt64(), and long instead of int, and
make sure the expression evaluates using long.
|
|
|
|
|
so if you are correct, this would work:
IntPtr myIntPtr1 = (IntPtr)0x1009624;
int myIntOffset = 0x1b;
IntPtr myIntPtr2 = new IntPtr(myIntPtr1.ToInt32() + myIntOffset);
|
|
|
|
|
same thing again...it's just adding them together in hex and converting them to decimal...not the pointer of the process's memory at all! any suggestions?
|
|
|
|
|
but that does work:
0x1009624 + 0x1b = 0x100963F
is the same as
16815652 + 27 = 16815679
which is what the code produces. hex, decimal, they're both integer values so it's straight integer addition, what are you expecting to happen?
|
|
|
|
|
If you know what pointers are or have had a little experience with ASM, then you know what pointers are. They are addresses that change positions every time the program is reopened, or rather pointers go to the address that changes ever time you reopen the application. If it were as simple as adding them together, I would just use 0x100963f rather than wasting time adding two together...for example in an old game that i used to play, the value for your population was a pointer, and it was not the address+offset...in fact if you took the address and made its offset 0, it would return a completely different address, and if you added to that offset, it would increase the address. Confusing? Here's what i mean:
address: 00400000
offset: 0
address of pointer: A48DAC8
or something like that
but if you increase the offset, it adds to the address of the pointer so:
address: 00400000
offset: b14
address of pointer: A48E5DC
I know it can be done in c++ and delphi and I think it can be done in C#, but i'm not sure exactly how to do it.
|
|
|
|
|
A pointer is a variable that holds a memory address and a memory address is an integer value, nothing more, nothing less. It's a given that the pointers you're using are going to change every time that you run an application because every time it's run there's no guarantee that the OS is going to assign it the same memory region. That's just common sense.
The explanation and example you've provided involving the "address", "offset" and "address of pointer" show one of two things:
a) your idea of what a pointer is is not correct or
b) you're misusing terminology to describe the situation
Either way, the fact remains that in C#, this style of memory management is completely outdated. C# is a Garbage Collected language so that you don't have to worry about where in memory things are; if your program relies on pointer arithmetic and memory regions to get it's job done, then you've picked the wrong language to implement your design.
|
|
|
|
|
|
OK, you DO know what pointers are, we're just using different terminology, and if you want to use C# then there's no reason to use them. The "master" that you're referencing leaves out something very important about pointers and memory: those "Static memory addresses" and "Dynamic memory locations" aren't just pulled out of thin air. Those addresses MUST be reserved by your application in some way so that nothing overwrites your data there. The example he's using seems to be using Intel Assembly - assembly language is a whole different ballgame from any high level language. In assembly you have to know the address of all your data because there isn't the same concept of a variable like there is C/C++/C#/JAVA/etc. See here[^] for the proper usage of pointers in C++. In C# forget about pointers entirely until you're Marshaling data between managed and unmanaged code.
|
|
|
|
|
Well he did it in Delphi coding, and I've seen it done in c++...but i guess c# is different...thanks for the help anyways...
Edit:Since pointers are out of the question, I need to know how to edit OpCodes directly, this can be done by simply editing the Array of Byte of that address, also known as the Hex Dump. It is usually a long hexidecimal number, divided up in segments of 2. Example: 0e 85 fe 8a 9d ba 80. The opcode and Array of Byte are directly connected.
|
|
|
|
|
I guarantee you in whatever high level language he did it in (whoever "he" is) he preallocated the memory region using some form of new or by creating variables or he's reading/writing to a some file.
I think you're still missing the point that I'm trying to get across here - forget about addresses entirely in C#. Store your data in objects!!! The opcode thing is an array of bytes? So create a byte[] named opCodes and store your opcodes in it. It's easier to use the hex value? Then create an Int64 named opCodeHexDump and use that to modify it's value. There's absolutely no reason whatsoever to have to know the address where the data is stored in memory.
What are the OpCodes, anyway? Do you mean assembly level operation codes - as in the translation of assembly into machine code? Or are they just some internal op codes in your game?
|
|
|
|
|
Opcodes and Array of Bytes are what you get when you disassemble and look at the memory of a process.
Here's a pic:
http://www.tonyschr.net/images/ollydbg.png
the opcodes are the PUSH DWORD, PUSH EDI, JNE notepad.exe, CALL DWORD, and ect...
the arrays of bytes are the hexidecimal values right between the opcodes and the addresses.
and by editing the array of bytes, you can change the opcodes, thus doing anything you want to an external process.
Edit: May have forgotten to mention this, but you can change the opcode by changing the value of an address too, but changing the array of byte, is easier.
|
|
|
|
|
That's what I was afraid of. There is absolutely no acceptable reason to modify the execution of an external process like this. This is called hacking, stop it now.
|
|
|
|
|
Call it what you want...there's nothing wrong with it.
|
|
|
|
|
Alright kiddo, here's the last reply that you're going to get from me because now you're just wasting my time.
I'm glad that you have no idea what the f*** you're doing because changing external processes by modifying their op codes is bad. Like I said before: there is absolutely no justifiable reason to do this. The only applications that behave this way are classifiable as viruses, and if you think there's nothing wrong with it wait until one f***s you over - or modifies the op codes of something that you wrote without your permission. It'll be a big deal then.
Look, you're profile says that you're 15 so take a lesson from somebody that's been using computers longer than you've been on this Earth. Learn Some Ethics. You know how marijuana is the gateway drug? well innocent little programs like you're doing are the gateway hack. Maybe it's for a game now but later on when you finish your education and get a real job you won't be writing the next evolution of Tetris. When you're working on sh*t that matters you won't get away with crap like this.
Or totally forget that you're doing something that's unethical. You're also writing code that is by design destabilizing your operating system. Bugs that arise from this stuff are near impossible to track down because their side effects are completely random. Doing this is just plain bad coding practice.
My involvement in this is now over.
|
|
|
|
|
That's OK, I was only doing this for fun. I can just use OllyDbg to permanently modify the opcodes, or use cheat engine to temporally modify them...but I've figured it out, and yes it is useless to do it in c#...there are much easier ways.
|
|
|
|
|
By the way, you can access pointers directly using an unsafe context -- look into this if you still feel like doing it in C#.
As for accessing certain bytes directly, you can use a mask and do a bitwise-AND and then bit-shift to move it into position.
uint x = 9;
uint MASK = 0xFFFFFFF8;
uint result = (x & MASK) >> 3;
if (result == 1)
{
Console.WriteLine("4th bit is a 1!");
}
else
{
Console.WriteLine("4th bit is a 0!");
}
|
|
|
|
|
what you call a pointer is not a pointer to the majority of us.
I think most assembly languages would call your operation "offset indirect
addressing" or something of that nature. In text: take the given address, load
an address from where it points, add the offset to it, and consider that the
effective address of the operation at hand.
That is quite different from a pointer, which offers no more than one level
of indirection: take the pointer value and consider that the effective address of
the operation at hand. See for isntance here.[^], maybe not the most technical reference, but good
enough in this matter.
The pointers that exist in C, C++, C# and many other languages obey the definition
above. Whereas the former definition is implemented in most (but not all)
handles used by Windows (all with an offset of zero, hence just a double
indirection)
FYI if the offset is to be multiplied by the size of the operand (in bytes),
then it is called "indexed indirect addressing" instead of "offset indirect
addressing".
Hope this clarifies why you could not recognize all the correct answers
given to you.
|
|
|
|
|
Could you give me a link to something that could help me with reading/writing to pointers? Or whatever it is that I am exactly talking about. Thanks...
|
|
|
|
|
whatever clever addressing modes have been defined, you must implement them
yourself. The only basic operations are read direct (i.e. from a given address)
and write direct. All indirections, double indirections, offsets, indexing,
have to be programmed from that, step by step, unlike assembly code
where they exist as basic functionality to improve code density and execution time.
Of course there is nothing that stops you from putting complex addressing modes
in separate methods; example: IntPtr eaOffsetIndirect(IntPtr base, int ofs) could
use base, read an int thru it, add offset, and return that as an IntPtr, so
the caller can immediately operate on the intended operand.
Before you ask, yes you could write a native code function that performs any
complex addressing scheme your CPU provides, but calling it (which requires
P/Invoke to cross the managed/unmanaged boundary) is likely to cause more
overhead than executing it step-by-step in a higher-level language (such as C#).
|
|
|
|
|
The problem for me is that I can't use assembly for this application, I need to do some other things such as sending keystrokes, mouse commands, moving the mouse, checking global hotkeys, and I've already written 80% of the code...so I'd like to finish it in C#...it's not a very large application so I'm not worried about causing too much clutter, and I'm only reading two pointers. So I'd like some more info on it PLEASE KTHX!;)
|
|
|
|
|