I want to clobber all load instructions - essentially, I want to find all load instructions, and after the load is complete I want to modify the value in the register that stores the value that was read from memory.
To do so, I instrument all instructions and when I find a load I insert a call to some function that will clobber the write register after the load. I pass in the register that needs to be modified (i.e. the register containing the data loaded from memory) using PIN_REGISTER*
.
Assuming I know the type of data that was loaded (i.e. int, float, etc.) I can access the PIN_REGISTER
union according to the data type (See this). However, as you can see in the link, PIN_REGISTER
stores an array of values - i.e. it doesn't store one signed int but rather MAX_DWORDS_PER_PIN_REG signed ints.
Will the value loaded from memory always be stored at index 0? If for instance, I load a 32 bit signed int from memory into a register, can I always assume that it would be stored at s_dword[0]
? What if for instance I write to the 8 bit AH/BH/CH/DH registers? Since these correspond to "middle" bits of 32 bit registers, I assume the data would not be at index 0 in the array?
What's the easiest way for me to figure out which index in the array the loaded data is stored at?
If for instance, I load a 32 bit signed int from memory into a register, can I always assume that it would be stored at s_dword[0]?
Yes.
If you are in long mode and have, e.g., the RAX register, you have two DWORDs: the lower less significant 32 bits (index 0 in s_dword
) and the higher most significant 32 bits (index 1 in s_dword
).
What if for instance I write to the 8 bit AH/BH/CH/DH registers? Since these correspond to "middle" bits of 32 bit registers, I assume the data would not be at index 0 in the array?
Note: AH
is rAX[8:16]
(rAX is RAX or EAX), not really in the 'middle'.
It really depends on which member of the union you are accessing. If we stay with the s_dword
member (or dword
), then AH
is still in the "lowest" DWORD (index 0) of the 32 or 64-bit register. It' is at the same time in the high part (most significant 8 bits) of the lowest WORD (16-bit quantity).
// DWORD (32-bit quantity)
auto ah = pinreg->dword[0] >> 8;
auto al = pinreg->dword[0] & 0xff;
// still the same for word (16-bit quantity)
auto ah = pinreg->word[0] >> 8;
auto al = pinreg->word[0] & 0xff;
// not the same for byte (8-bit quantity)
auto ah = pinreg->byte[1];
auto al = pinreg->byte[0];
What's the easiest way for me to figure out which index in the array the loaded data is stored at?
Hard to say, it just seems natural to me to know at which index it is. As long as you know the size of the various denominations in the union, it's quite simple:
byte
: 8 bitsword
: 16 bitsdword
: 32 bitsqword
: 64 bitsHere's a crude drawing with different sizes:
+---+---+---+---+---+---+---+---+
| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | byte
+---+---+---+---+---+---+---+---+
+-------+-------+-------+-------+
| 3 | 2 | 1 | 0 | word
+-------+-------+-------+-------+
+---------------+---------------+
| 1 | 0 | dword
+---------------+---------------+
+-------------------------------+
| 0 | qword
+-------------------------------+
^ ^
MSB LSB
The same with AL and AH (you can see that AH is byte[1]
and AL is byte[0]
both are in word[0]
, dword[0]
and qword[0]
):
+---+---+---+---+---+---+---+---+
| 7 | 6 | 5 | 4 | 3 | 2 | AH| AL| byte
+---+---+---+---+---+---+---+---+
+-------+-------+-------+-------+
| 3 | 2 | 1 | 0 | word
+-------+-------+-------+-------+
+---------------+---------------+
| 1 | 0 | dword
+---------------+---------------+
+-------------------------------+
| 0 | qword
+-------------------------------+
^ ^
MSB LSB