I'm trying to hack another program by changing the EIP of it. There are two programs running, one is the target, that tells where the function that is the "core-function"(e.g. a function that receive a password string as a parameter and returns true or false) is in memory.
Then now that I know where the core-function is I wanna modify the EIP with the other program so the target program can call my function and simply get a true out of it and print out a beautiful "access granted".
My code is now like this:
Target Program:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int checkPwd(char *pwd)
{
printf("\nstill in the function\n");
if(strcmp(pwd, "patrick") == 0) return true;
else return false;
}
int main()
{
char pwd[16];
printf("%d", checkPwd);
scanf("%s", &pwd);
system("pause");
if(checkPwd(pwd)) printf("Granted!\n");
else printf("Not granted\n");
system("pause");
}
Attacker Program:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <memory.h>
int returnTrue()
{
return true;
}
int main()
{
int hex;
scanf("%d", &hex);
memcpy((void*)hex, (void*)returnTrue, sizeof(char)*8);
system("pause");
}
I wanna add that I tried to put the hex code directly(without the scanf part) in the attacker program and did not work, it crashed.
So I think I'm missing some part of the theory in here. I'd be glad to know what is it.
Thanks in advance.
This won't work—the processes occupy different memory spaces!
Modern operating systems are designed to protect user programs from exactly this kind of attack. One process doesn't have access to the memory of another—and indeed, the addresses of data are only valid inside that process.
When a program is running, it has its own view of memory, and only can "see" memory that the kernel has instructed the memory management unit (MMU) to map for it.
Some references:
Mapping of Virtual Address to Physical Address
Printing same physical address in a c program
Why are these two addresses not the same?
It is possible to inject a function into another process but it is a little more involved than you think. The first thing is you need the proper length of the function you can do this by creating two functions.
static int realFunction() { ... }
static void realFunctionEnd() {}
Now when you copy the function over you do the length of:
realFunctionEnd - realFunction
This will give you the size. Now you cannot just call the other functions because as stated they are not guranteed to be at the same address in the other process, but you can assume that , I will assume windows, that kernal32.dll is at the same address so you can actually pass that to the realFunction when you create a remote thread.
Now, as to your real issue. What you need to do is to either inject a dll or copy a function over into the other process and then hook the function that you need to change. You can do this by copying another function over and making that code executable and then overwriting the first five bytes of the target function with a jump to your injected code, or you can do a proper detour type hook. In either case it should work. Or, you can find the offset into the function and patch it yourself by writing the proper op codes in place of the real code, such as a return of true.
Some kind of injection or patching is required to complete this, you have the basic idea, but there is a little more to it than you think at the moment. I have working code for windows to copy a function into another process, but I believe it is a good learning experience.
Related
Im trying to copy a function i have to an executable page and run it from there, but i seem to be having some problems.
Here is my code:
#include <stdio.h>
#include <string.h>
#include <windows.h>
int foo()
{
return 4;
}
int goo()
{
return 5;
}
int main()
{
int foosize = (int)&goo-(int)&foo;
char* buf = VirtualAlloc(NULL, foosize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (buf == NULL)
{
printf("Failed\n");
return 1;
}
printf("foo %x goo %x size foo %d\n", &foo, &goo, foosize);
memcpy (buf, (void*)&foo, foosize);
int(*f)() = &foo;
int ret1 = f();
printf("ret 1 %d\n", ret1);
int(*f2)() = (int(*)())&buf;
int ret2 = f2 (); // <-- crashes here
printf("ret2 %d\n", ret2);
return 0;
}
I know some of the code is technically UB ((int)&goo-(int)&foo), but it behaves fine in this case.
My question is why is this not working as expected?
It seems to me i mapped a page as executable and copied an existing function there and im just calling it.
What am i missing?
Would this behave differently on linux with mmap?
Thanks in advance
As everyone has already stated in comments, this is totally undefined behavior and should never really expect to work. However, I played with your code some with the debugger and realized the reason it's not working (at least in Cygwin gcc compiler) is you're creating f2 incorrectly to point to the the address of the pointer storing the allocated memory, namely buf. You want to point to the memory that buf points to. Therefore, your assignment should be
int(*f2)() = (int(*)())buf;
With that change, your code executes for me. But even if it works, it might break again as soon as you make any additional changes to the program.
Well I made a try of your code with MVSC 2008 in debug mode. Compiler happens to create a jmp table with relative offsets, and &foo and &goo are just entries in that table.
So even if you have successfully created an executable buffer and copied the code (much more than was useful...) the relative jump now points to a different location and (in my example) soon fell in a int 3 trap!
TL/DR: as compiler can arrange its code at will, and as many jump use relative offsets, you cannot rely on copying executable code. It is really Undefined Behaviour:
if compiler had been smart enough to just generate something like :
mov AX, 4
ret
it could have worked
if compiler has generated more complicated code with a relative jump it just breaks
Conclusion: you can only copy executable code if you have full control on the binary machine code for example if you used assembly code and know you will have no relocation problem
You need to declare foo and goo as static or will have to disable Incremental Linking.
Incremental linking is used to shorten the linking time when building your applications, the difference between normally and incrementally linked executables is that in incrementally linked ones each function call goes through an extra JMP instruction emitted by the linker.
These JMPs allow the linker to move the functions around in memory without updating all the CALL instructions that reference the function. But it's exactly this JMP that causes problems in your case. Declaring a function as static prevents the linker from creating this extra JMP instruction.
I'm trying to call the oopsIGotToTheBadFunction by changing the return address via the user input in goodFunctionUserInput.
Here is the code:
#include <stdio.h>
#include <stdlib.h>
int oopsIGotToTheBadFunction(void)
{
printf("Gotcha!\n");
exit(0);
}
int goodFunctionUserInput(void)
{
char buf[12];
gets(buf);
return(1);
}
int main(void)
{
goodFunctionUserInput();
printf("Overflow failed\n");
return(1);
}
/**
> gcc isThisGood.c
> a.out
hello
Overflow failed
*/
I've tried loading the buffer with 0123456789012345 but not sure what to put for the rest of it to get the address. The address is 0x1000008fc.
Any insights or comments would be helpful.
I'm going to give this the benefit of the doubt and presume this is an exercise intended to learn about the stack (perhaps homework) and not learning how to do anything malicious.
Consider where the return address of goodFunctionUserInput is on the stack and what would happen if you changed it. You may wish to check the disassembly to see how much space on the stack the compiler made for goodFunctionUserInput and where exactly buf is. When you figure out how long a string to enter, consider the endianness of the machine and what that means for the address you want to overwrite into the return address of goodFunctionUserInput. Worrying about what sorts of awful things this does to the stack isn't important here as your function you want to call simply calls exit.
I want to take a piece of code, copy it into a global array and execute it from there.
In other words, I am trying to to copy a bunch of instructions from the code-section into the data-section, and then set the program-counter to continue the execution of the program from the data-section.
Here is my code:
#include <stdio.h>
#include <string.h>
typedef void(*func)();
static void code_section_func()
{
printf("hello");
}
#define CODE_SIZE 73
// I verified this size in the disassembly of 'code_section_func'
static long long data[(CODE_SIZE-1)/sizeof(long long)+1];
// I am using 'long long' in order to obtain the maximum alignment
int main()
{
func data_section_func = (func)data;
memcpy((void*)data_section_func,(void*)code_section_func,CODE_SIZE);
data_section_func();
return 0;
}
I might have been naive thinking it could work, so I'd be happy to get an explanation why it didn't.
For example, after a program is loaded into memory, does the MMU restrict instruction-fetching to a specific area within the memory address space of the process (i.e., the code-section of the program)?
For the protocol, I have tested this with VS2013 compiler over a 64-bit OS and an x64-based processor.
Thanks
Windows (and many other modern OSes) by default sets the data section as read/write/no-execute, so attempting to "call" a data object will fail.
Instead, you should VirtualAlloc a chunk of memory with the PAGE_EXECUTE_READWRITE protection. Note, it may be necessary to use FlushInstructionCache to ensure the newly-copied code is executed.
I need somebody to edit the title, I can't find better title.
Assume a have this simple program called source.exe:
#include <stdio.h>
int main()
{
int a = 5;
printf("%p", &a);
return 0;
}
I want to write another application, change.exe, that changes a in the above.
I tried something like this:
int main()
{
int * p = (int*) xxx; // xxx is what have printed above
*p = 1;
printf("%d", *p);
return 0;
}
It doesn't work. assuming I have Administrator rights, is there a way to do what I've tried above? thanks.
In first place, when you run the second program, the a in the first will be long gone (or loaded in a different position). In second place, many OS's protect programs by loading them in separate spaces.
What you really seem to be looking for is Inter-Process Communication (IPC) mechanisms, specifically shared memory or memory-mapped files.
On most traditional computers that people deal with, the operating system makes use of virtual memory. This means that two processes can both use address 0x12340000 and it can refer to two different pieces of memory.
This is helpful for a number of reasons, including memory fragmentation, and allowing multiple applications to start and stop at random times.
On some systems, like TI DSPs for example, there is no MMU, and thus no virtual memory. On these systems, something like your demo application could work.
I was feeling a bit adventurous, so I thought about writing something like this under Windows, using the WinAPI, of course. Like Linux's ptrace, the calls used by this code should only be used by debuggers and aren't normally seen in any normal application code.
Furthermore, opening another process' memory for writing requires you to open the process handle with PROCESS_VM_WRITE and PROCESS_VM_OPERATION privileges. This, however, is only possible if the application opening the process has the SeDebugPriviledge priviledge enabled. I ran the application in elevated mode with administrator privileges, however I don't really know if that has any effect on the SeDebugPriviledge.
Anyhow, here's the code that I used for this. It was compiled with VS2008.
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char cmd[2048];
int a = 5;
printf("%p %d\n", &a, a);
sprintf(cmd, "MemChange.exe %lu %x", GetCurrentProcessId(), &a);
system(cmd);
printf("%p %d\n", &a, a);
return 0;
}
And here's the code for MemChange.exe that this code calls.
#include <windows.h>
#include <stdio.h>
int main(int argc, char **argv)
{
DWORD pId;
LPVOID pAddr;
HANDLE pHandle;
SIZE_T bytesWritten;
int newValue = 666;
sscanf(argv[1], "%lu", &pId);
sscanf(argv[2], "%x", &pAddr);
pHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pId);
WriteProcessMemory(pHandle, pAddr, &newValue, sizeof(newValue), &bytesWritten);
CloseHandle(pHandle);
fprintf(stderr, "Written %u bytes to process %u.\n", bytesWritten, pId);
return 0;
}
But please don't use this code. It is horrible, has no error checks and probably leaks like holy hell. It was created only to illustrate what can be done with WriteProcessMemory. Hope it helps.
Why do you think that this is possible - debuggers can only read?
If it was possible then all sorts of mayhem could happen!
Shared memory springs to mind.
Recently I came across the problem of geting 'Oops, Spwan error, can not allocate memory' while working with one C Application.
To understand the File Descriptor and Memory management better I give a try this sample program and it gives me shocking result.
Here is the code.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int ac, char *av[]);
int main(int ac, char *av[])
{
int fd = 0;
unsigned long counter=0;
while (1)
{
char *aa = malloc(16384);
usleep(5);
fprintf(stderr,"Counter is %ld \n", counter);
fd = fopen("/dev/null",r")
}
return 0;
}
Here in the sample program I am trying to allocate memory every 5 micro second and also open a file descriptor at the same time.
Now when I run the program it started increasing the memory and also file descriptor star increasing, but memory increase upto 82.5% and file descriptor increase upto 1024. I know 'ulimit' set this parameter and it is 1024 by default.
But this program must crash by eating the memory or it should gives error ' Can't spawn child', but it is working.
So Just wanted to know why it is not crashing and why it is not giving child error as it reached file descriptor limit.
It's not crashing probably because when malloc() finds no more memory to allocate and return, it simply returns NULL. Likewise, open() also just returns a negative value. In other words, the cooperation of your OS and the standard library is smarter than it would enable your program to crash.
What's the point in doing that?
Plus on linux, the system won't even eat up the memory if nothing is actually written on "aa".
And anyway, if you could actually take all the memory (which will never happen, for Linux and *bsd, don't know about windows), it would just result in making the system lag like hell or even freeze, not just crashing your application.