I'd like to be able to change only one byte at a certain address with gdb.
The set * command always changes 4 counting from an address and if you don't provide all four it fills the rest with zeroes (or ffs depending on the signedness).
The syntax I'm using is set * {address}=0x{bytes}
treat address as pointer to char type
(gdb) set {char}address = 0x{bytes}
Related
I am trying an example in the documentation: "x/4wx 0x54320". I expect to see 16 hex characters. Instead I get an error: "Cannot access memory at address 0x54320".
According to documentation: "address is the address where you want GDB to begin displaying memory: it is always interpreted as an integer address of a byte of memory.".
Is GDB taking "0x54320" as the location to start looking, or the address (pointer) to the location to start looking?
Anyway, all I want is to see the bytes stored starting at "0x54320". How do I accomplish this, please?
x/4wx 0x54320 is incorrect. You probably mean x/4xw 0x54320: display 4 words as hex beginning at address 0x54320. If that address is a pointer, you'll see the value of the pointer, i.e., the address it holds.
0x54320 looks suspicious to me. It's a rare address that just happens to count down in hex. But, maybe you're just lucky.
Assume there is a memory mapped device at address 0x1ffff670. The device register has only 8-bits. I need to get the value in that register and increment by one and write back.
Following is my approach to do that,
In the memory I think this is how the scenario looks like.
void increment_reg(){
int c;//to save the address read from memory
char *control_register_ptr= (char*) 0x1ffff670;//memory mapped address. using char because it is 8 bits
c=(int) *control_register_ptr;// reading the register and save that to c as an integer
c++;//increment by one
*control_register_ptr=c;//write the new bit pattern to the control register
}
Is this approach correct? Many thanks.
Your approach is almost correct. The only missing part - as pointed out in the comments on the question - is adding a volatile to the pointer type like so:
volatile unsigned char * control_register_ptr = ...
I would also make it unsigned char, since that is usually a better fit, but that's basically not that much different (the only meaningful difference would be when shifting the value down.)
The volatile keyword signals to the compiler the fact that the value at that address might change from outside the program (i.e. by code that the compiler doesn't see and know about.) This will make the compiler more conservative in optimizing loads and stores away, for example.
There is a function in this program, that currently returns a 1. I would prefer for it to return a 0.
uregs[R_PC] is the program counter.
arg0 is the program counter offset from where we left the function (assembly, "ret").
From this I deduce: we can add the offset to the program counter, uregs[R_PC]+arg0, to find the address of the return value.
I have allocated a 32-bit "0", and I try to write 2 bytes of it into the address where the return value lives (our function expects to return a BOOL16, so we only need 2 bytes of 0):
sudo dtrace -p "$(getpid)" -w -n '
int *zero;
BEGIN { zero=alloca(4); *zero=0; }
pid$target::TextOutA:return {
copyout(zero, uregs[R_PC]+arg0, 2);
}'
Of course I get:
dtrace: error on enabled probe ID 2 (ID 320426: pid60498:gdi32.dll.so:TextOutA:return): invalid address (0x41f21c) in action #1 at DIF offset 60
uregs[R_PC] is presumably a userspace address. Probably copyout() wants a kernel address.
How do I translate the userspace address uregs[R_PC] to kernel-space? I know that with copyin() we can read data stored at user-space address, into kernel-space. But that doesn't give us the kernel address of that memory.
Alternatively: is there some other way to change the return value using DTrace?
DTrace is not the right tool for this. You should instead use a debugger like dbx, mdb or gdb.
In the meantime, I'll try to clarify some of the concepts that you've mentioned.
To begin, you may well see in the source code for a simple function that there is a single return. It is quite possible that the compiled result, i.e. the function's machine-specific implementation, also contains only a single point of exit. Typically, however, the implementation is likely to contain more than one exit point and it may be useful for a developer to know from which specific one a function returned. It is this information, described as an offset from the start of the function, that is given by a return probe's arg0. Your D script, then, is attempting to update part of the program or library itself; although the addition of arg0 makes the destination address somewhat random, the result is most likely still within the text section, which is read-only.
Secondly, in the common case, a function's implementation returns a value by storing it in a specific register; e.g. %rax on amd64. Thus overriding a return value would neccessitate overriding a register value. This is impossible because DTrace's access to the user-land registers is read-only.
It is possible that a function is implemented in such a way that, as it returns, it recovers the return value from a specific memory location before writing it into the appropriate register. If this were the case then one could, indeed, modify the value in memory (given its location) just before it is accessed. However, this is going to work for only a subset of cases: the return value might equally be contained in another register or else simply expressed as a constant in the program text itself. In any case, it would be far more trouble than it's worth given the existence of more appropriate debugging tools.
I have a structure that describes a bitmap. It looks like this
struct bitmap {
int XSize;
int YSize;
unsigned char *pData;
};
When an instances of this structure is initialized pData points to thousands of random-like but non-zero bytes. When I print the instance of the structure GDB shows a lot of meaningless bytes. That very time consuming. When the disp of such a variable is active I get the output for each step what delays debugging.
Is there a GDB option that limits the output length?
When the bytes are meaningless I could change the type of pData to void *. But since the structure is used in a precompiled library the type can't be changed. Can the type that GDB uses for print and disp be "overridden"?
As Paul has pointed out the answer in this question gives the correct command to allow unlimited length.
To limit the length you need the command
set print elements n
where n is the maximum number of elements. Setting n to 0 gives the unlimited length.
Setting print elements 4 will limit the number of pData characters to 4, but it will also limit all other strings and arrays, which could be quite annoying (e.g. print filename would produce /tmp... when the actual value is /tmp/foobar.
A possibly better approach is to write a Python pretty-printer for struct bitmap (assuming you have sufficiently recent GDB). See this answer on how to do that.
I've yet again been faced with the challenge of a slight hack in my code to accommodate for an unmodifiable library of some poorly written code.
After hours of research (after finding out you cannot pass any sort of state to a function pointer), I need to NOP out the ASM bytes within the function header that reset EAX to 0xCCCCCCCC.
By using the built in VC++ debugger to obtain the 'address' of the function and manually creating an array of bytes entry in cheat engine (which is surprisingly useful for this sort of thing), it successfully pulled up the bytes and I could NOP the 5 byte sequence manually.
However, doing this programmatically is a little different.
When I do any of the following, the address is significantly higher than what the debugger is reporting, this giving me a pointer to the wrong bytes.
unsigned int ptr = reinterpret_cast<unsigned int>(testhack);
unsigned char* tstc = (unsigned char*)&testhack;
FARPROC prc = GetProcAddress(GetModuleHandle("mod.dll"), "testhack"); // Still
// returns the incorrect address (same as the previous two)
What is the debugger doing to find the correct address? How can I find the correct address programmatically?
Presumably the function address is in a DLL. In that case what you're seeing is the loader relocating the addresses of for example &testhack into the correct location for the memory in which your program is loaded. The debugger probably already knows about the relocations and is helpfully automatically taking care of that for you, allowing you to modify the bytes.
Unfortunately I'm not aware of any mechanism to work around this, but if you link statically the addresses will be fixed at link time rather than runtime.
Figured it out.
Totally forgot about (what I believe are called) lookup tables. The address I was receiving was the pointer to the lookup table entry, which was a simple 5-byte unconditional JMP to the real function body. All I had to do was get the offset, add it to the end of the lookup table entry, and then I had my correct address.
Here is the code to reach the correct start address of the function.
// Get the lookup table address
const char* ptr = (const char*)&testhack;
// Get the offset (+ 1 byte retrieved as a long)
unsigned int offset = (unsigned int)(*((unsigned int*)(ptr + 1)));
// Add to the original look up pointer, +5 (the offset starts after the
// end of the instruction)
const char* tst = (const char*)(ptr + offset + 5);
tst then holds the correct address!
As of now, the calling ASM instructions put the pointer to the struct containing the function pointers into EAX. Normally, the callback function would reset EAX. However, I've applied this hack and NOP'd out that part. The first lines of code within the function create a local pointer, and then inline assembly to mov [ptr],eax the address into the pointer. I can then use the pointer normally.