I have 2 questions:
The Pe32 header consists of many subheaders. One of them is the optional header. MSDN says that the last element of IMAGE_OPTIONAL_HEADER is a pointer to the first IMAGE_DATA_DIRECTORY struct of the executable. When I look into the WIN32N.INC for NASM everything is the same as listed in MSDN with the difference that the pointer to the first struct has the size 8 bytes instead of 4 (like a normal 32bit pointer):
STRUCT IMAGE_OPTIONAL_HEADER
.Magic RESW 1
...
.DataDirectory RESQ 1 <----- why RESQ?
ENDSTRUC
When I want to copy the 16 DataDirectories out of the binary data I stored as a "variable" in NASM into an struct: Is it ok to create a struct with 32 entries (Export Directory RVA + size, Import Directory RVA + size, etc...) and have the pointer to the first DataDirectory struct in the optional header point to its beginning? Because otherwise there would be no way to get from the first element to the other ones, wouldn't it?
Can someone explain this?
DataDirectory is an array of structs, not a pointer.
MSDN tells you that the layout is actually
typedef struct _IMAGE_DATA_DIRECTORY {
DWORD VirtualAddress;
DWORD Size;
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
and your .INC file just defines it as a QWORD for some unknown reason.
WinNT.h in the SDK defines the optional header as:
...
DWORD NumberOfRvaAndSizes;
IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;
where IMAGE_NUMBEROF_DIRECTORY_ENTRIES is 16.
You should not just copy 16 items, the NumberOfRvaAndSizes member specifies the size and it could be < 16.
Related
I am trying to understand why this printf statement gives two different outputs; I think I have a decent understanding of one of the outputs.
Here is the code:
const char *ptr = "hello";
const char array[] = "hello";
//Question 2
printf("%zu %zu\n", sizeof(ptr),sizeof(array));
Now I understand why sizeof(array) returns six: this is because the length of "hello" is 6 plus an additional null terminator.
But I do not understand why sizeof(ptr) is 8; my guess is that all memory addresses in C occupy 8 bits of memory hence the size is 8. Is this correct?
The C language, itself, doesn't define what size a pointer is, or even if all pointers are the same size. But, yes, on your platform, the size of a char* pointer is 8 bytes.
This is typical on 64-bit platforms (the name implies 64-bit addressing which, with 8 bits per byte, is 64/8 = 8 bytes). For example, when compiling for a Windows 64-bit target architecture, sizeof(char*) is 8 bytes; however, when targeting the Windows 32-bit platform, sizeof(char*) will be 4 bytes.
Note also that the "hello" string literal/array is 6 bytes including the nul terminator.
sizeof(ptr) returns 8 because it's the size of a pointer on a typical 64-bit architecture. The pointer ptr is a pointer to a constant character, so its size is 8 bytes on a 64-bit system. The value stored in the pointer is the memory address of the first character in the string literal "hello", so ptr takes up 8 bytes of memory, not 6.
The size of a pointer is platform-dependent and can be different on different architectures. On a 32-bit system, the size of a pointer would typically be 4 bytes.
So I have a struct:
typedef struct {
int x = 0;
} Command;
and global vectors:
vector<Command> cmdList = {}; vector<Event*> eventList = {};
I push_back, erase and clear the vector in another .cpp file. This gets pushed back into:
vector<Command> cmdsToExec = {}; inside per Event struct created. I use this to push_back:
eventList.push_back( new Event() ); eventList[int( eventList.size() ) - 1]->cmdsToExec = cmdList;
My problem A) these Event*s can't be erased with delete and B) is that Valgrind gives this error while trying to determine the size of the cmdsToExec:
==25096== Invalid read of size 8
==25096== at 0x113372: std::vector<Command, std::allocator<Command> >::size() const (stl_vector.h:919)
==25096== by 0x11C1C7: eventHandler::processEvent() (eventHandler.cpp:131)
==25096== by 0x124590: main (main.cpp:88)
==25096== Address 0x630a9e0 is 32 bytes inside a block of size 56 free'd
==25096== at 0x484BB6F: operator delete(void*, unsigned long) (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==25096== by 0x11C116: eventHandler::processEvent() (eventHandler.cpp:222)
==25096== by 0x124590: main (main.cpp:88)
==25096== Block was alloc'd at
==25096== at 0x4849013: operator new(unsigned long) (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==25096== by 0x11B4A5: eventHandler::createEvent() (eventHandler.cpp:58)
==25096== by 0x11B412: eventHandler::doState() (eventHandler.cpp:41)
==25096== by 0x124575: main (main.cpp:83)
Ive tracked it to the line:
while( int( eventList[0]->cmdsToExec.size() ) > 0 ) {
Im not trying to solve this specific problem, its more about how to properly delete and unallocate a dynamic pointer from a global vector of dynamic pointers. That being said there are no objects (and I want to keep it that way). Will I need a struct deconstructor (no pun intended)? Also I dont believe cmdList vector ever has a memory leak according to this error message, also as Im clearing it all at once.
My thoughts on fixing this are to place both global vectors into my main() function and pass them into the program from there. I thought it would be unnecessary to do this and would slow the program down. Thinking now, I guess it wouldn't.
My guess is that this is a problem related to the order of destruction of static/global objects.
C++ guarantees that for a given translation unit (i.e., a cpp source file) then statics/global objects get created in the order that they are defined, and they are destroyed in the reverse order.
C++ gives no guarantee between different translation units.
My recommendations are:
Avoid statics/globals. Move them to be class members if possible.
If you have any dependencies between statics/globals then put them all in the same source file so that you have control over the order of their creation and destruction.
I'll use a simple specific example to illustrate what I'm trying to do.
file main.c:
#include <stdio.h>
unsigned int X;
int main()
{
printf("&X = 0x%zX\r\n", &X);
return 0;
}
I want to know if it's possible (using a linker-script/gcc options) to manually specify an address for X at compile/link time, because I know it lies somewhere in memory, outside my executable.
I only want to know if this is possible, I know I can use a pointer (i.e. unsigned int*) to access a specific memory location (r/w) but that's not what I'm after.
What I'm after is making GCC generate code in which all accesses to global variables/static function variables are either done through a level of indirection, i.e. through a pointer (-fPIC not good enough because static global vars are not accessed via GOT) or their addresses can be manually specified (at link/compile time).
Thank you
What I'm after is making GCC generate code in which all accesses to
global variables/static function variables … their addresses can be
manually specified (at link/compile time).
You can specify the addresses of the .bss and .data sections (which contain the uninitialized and initialized variables respectively) with linker commands. The relative placement of the variables in the sections is up to the compiler/linker.
If you need only individual variables to be placed, this can be done by declaring them extern and specifying their addresses in a file, e. g. addresses.ld:
X = 0x12345678;
(note: spaces around = needed), which is added to the compiler/linker arguments:
cc main.c addresses.ld
i was reading an example in assembly languaje, and i have a little doubt. We were using assembly only on our programs, but the last unit on the semester it's to merge it with turbo c (in-line assembly), and reading the code, there's a part which i don't quite get it:
Here's the assembly part:
dosseg
.model small
.code
public _myputchar
_myputchar PROC
push bp
mov bp,sp
mov dl,[bp+4]
mov ah,2
int 21h
pop bp
ret
_myputchar ENDP
END
And here's the C part:
#include<stdio.h>
extern void myputchar( char x );
char *str={"Hola Mundo\n"};
void main ( void )
{
while(*str)
myputchar(*str++);
getchar();
}
So, it's pretty straight forward, and the program works, but, what i don't get, it's the assembly code. The problem is, Why the base pointer (bp) it's pointing to +4? (mov dl,[bp+4]), I would think that you only had to mov dl,bp but i don't get why +4. If someone can help we, that would be really apretiated!. (in the include section i put the "" Because the formating tools it's giving me such headech -_-!
The argument (x) is pushed onto the stack before calling the function. After this, the call instruction will push the return address (2 bytes in this case) onto the stack, and the push bp at the beginning of the function will push another 2 bytes onto the stack.
So by now you've pushed 2+2 == 4 more bytes onto the stack after the argument. Since the stack grows downward that means that to get the argument you have to offset the pointer by +4 bytes.
The starting address of the string you want to print is at [bp + 4]. The current stack pointer is [bp]. Remember, the stack grows down.
Not used memcpy much but here's my code that doesn't work.
memcpy((PVOID)(enginebase+0x74C9D),(void *)0xEB,2);
(enginebase+0x74C9D) is a pointer location to the address of the bytes that I want to patch.
(void *)0xEB is the op code for the kind of jmp that I want.
Only problem is that this crashes the instant that the line tries to run, I don't know what I'm doing wrong, any incite?
The argument (void*)0xEB is saying to copy memory from address 0xEB; presumably you want something more like
unsigned char x = 0xEB;
memcpy((void*)(enginebase+0x74c9d), (void*)&x, 2);
in order to properly copy the value 0xEB to the destination. BTW, is 2 the right value to copy a single byte to program memory? Looks like it should be 1, since you're copying 1 byte. I'm also under the assumption that you can't just do
((char*)enginebase)[0x74c9d] = 0xEB;
for some reason? (I don't have any experience overwriting program memory intentionally)
memcpy() expect two pointers for the source and destination buffers. Your second argument is not a pointer but rather the data itself (it is the opcode of jnz, as you described it). If I understand correctly what you are trying to do, you should set an array with the opcode as its contetns, and provide memcpy() with the pointer to that array.
The program crashes b/c you try to reference a memory location out of your assigned space (address 0xEB).