tags:

views:

91

answers:

4

Hello. I want to make simple functions that given an offset (and knowing the base address of a library) can retrieve or set the value located in there.

Questions:

What are the pratical differences between types of memory?

What I want to know exactly is: with what do I have to be concerned with, to make it work transparently. For example, depending on the type of memory, do I have to use a different flag or setting to "Read + Write + Execute" works for all of them? And what about differences between Windows and Linux?

A: 

I don't know about *nix, but on Windows, you will not be able to write everywhere within a library. (Windows documentation calls them modules)

Pages in a library will be 4k or 8k in size (I think 8k was only on the Alpha AXP, which is obsolete now). The base address will be a multiple of 64k. Pages will either be copy-on-write or read-only. I believe all pages containing code will be copy-on-write. Pages containing data will be read-only or copy-on-write depending on how the data was declared.

You do not need to be concerned with flags or settings. You will either be able to write or you won't. You should always be able to read, as long as you stay with in the module boundaries.

You can only write to pages in your own process unless you use the Win32 API's ReadProcessMemory or WriteProcessMemory

Edit: based on comments

To change page protection flags, you use VirtualProtect or VirtualProtectEx

Be aware that if you change a page from read-only to read-write and then write to it, you risk changing not just memory, but also having your change written back to the library file. You should change the page protection to copy-on-write instead.

VirtualProtect can be used to change execute permissions on pages as well, for systems that support that.

John Knoeller
It's impossible that I don't have to be concerned with flags. I've dealt myself with memory that comes as read only and I have to make it writable. Namely, for functions patching.
A: 

You didn't state what language you are programming in, so I'm going to assume C and derivatives.

If you have an address, you can read the the byte at that address by casting it to a pointer and dereferencing:

unsigned char value = *(unsigned char *)address;

And if you want to write it:

*(unsigned char *)address = value;

In order for this to work, the page the address is in must be mapped into your address space with the appropriate permissions. If the page is not mapped or if you don't have the appropriate permissions, the OS will usually terminate your program (on Linux, it will generate a segment violation aka SEGV).

R Samuel Klatchko
C++. What I want exactly to do is: a person takes a look at a .dll or a .so and see a 4.0 and wants it to be 6.0. Or a "stuff" and wants it to be "thing". I want that he can take the offset from the base address (X) and that he can do set(x,16.0)
+1  A: 

Read, Write and Execute is possible under Linux, due to the nature of their elf32 linker when compiling programs, for instance, you can have one segment as read only, in another segment you can have it write only. Not sure if a linker under Windows can do that, I know they can have a segment that is shared by other programs...

Now, to make it work transparently, I assume you mean that for both windows and linux? Memory under both platforms are similar in concept, in that the kernel has put in protection in place between user land programs and kernel code.

In the old days of DOS, memory was split up into segment:offset which when combined together like this:

segment +
offset
---------
physical memory for that segment

for example:
B800 +
 0000
------
B8000  

That was to get around the quirk in the memory addressing mode as the DOS environment can only access 2^20 bytes of memory hence the segment+offset pair, which was used in 16bit mode.

Here's an example of 16bit code that can determine how many lines there are in a DOS screen:

int heightScreen(void)
{
    return (*(unsigned char far *) 0x484) + 1;
}

The segment is 0x484 which is located in the BIOS that tells how many lines there are.

In 32bit mode, it was just segment selector:segment (I think... not sure as I'm writing this from memory), depending on how the OS is designed, there are different ways of accessing the memory from the context of demand-paged, virtual and flat mode...the references to this can be found in the intel document in pdf on the internet here...the relevant document is '24143004.pdf' in which you can search)

The processor has ring0 mode which can execute privileged instructions and access to memory only. ring3 is where the user land domain of applications run in, they have restricted access to the privileged instructions (or none at all) and can access their own memory space. ring2 would be typically occupied by the device drivers which act as a middle-man between the kernel and user-land space. Also, the kernel would have provided call-gates or traps in there to request a certain privilege (only device drivers can do that).

If you want to access privileged memory and risk bringing the system down to its knees, under Linux, supply the suid bit to the program in question or run it as root. For Windows, you need to elevate the permissions of the code or perform code injection into the process memory, or more aptly, write a device driver to interact with kernel code/memory space and provide an API for the user land code to interact with.

If you do try to access a privileged instruction or memory that you have no access to, the kernel will shut down your program by killing the process as if saying "get lost, no way jose".

Hope this brief summary helps, Best regards, Tom.

tommieb75
Look. I have a library with a bunch of variables and functions. If I have the address of a function I know that I can set it writable and patch it to the bytes I want. But, I also know that there is but never worked with, different types of memory locations, namely ".rodata" , ".text" and ".data". What I want to do, is to, given an offset from the beginning of the library to patch any kind of memory.
Why would you want to patch it?
tommieb75
To change the behaviour of the libraries. The libraries belong to half life 1 based games and patching their memory permits endless changes of functionality.
Ahhh... now I see your reasoning behind the question...sorry if I waffled a bit too much.... :(
tommieb75
No problem. I guess I have problems in explaining what I want. thank you
A: 

I'm not sure under Windows, but in *nix I believe mmap may do the job... maybe, writing into dynamically linked memory is dangerous at best still though.

From your comments I would guess you would want to do something like

//in the library
void myfunction(){
  int x;
  x=x+1;
}

//in the client

uint8_t *ptr=(void*)&myfunction;
ptr[0]=some_opcode;

I must tell you, that is probably the most insecure thing I've seen. I know this is not possible with some secure OSs such as OpenBSD because it was W^X, and you can't use mmap because the executable was already linked to that fixed address, so it will break on any non-local variable accesses(on x86-64, I think it may on x86-32 as well)

Seriously. Why do you need to be able to do this kind of self-modifying code?

Earlz
Already responded but here it goes again: "To change the behaviour of the libraries. The libraries belong to half life 1 based games and patching their memory permits endless changes of functionality"
Why don't you just patch the libraries before the code runs? This would require some ELF/PE parsing, but much more possible than your current idea.
Earlz
That's ilegal and this is for a library for others use as they want. This is already done by others and is absolutely possible and easy. It's just that it is only made for Windows and I want to learn the differences for Linux.