-2

I am writting a self-mutation code , and its original value before overwrite is 1,but after the overwrite should be 42. I think I am missing some aspecs because I got 1 on both original and mutation overwrite. my complete code looks like this gist link , but the original source was written under *unix https://shanetully.com/2013/12/writing-a-self-mutating-x86_64-c-program/

#include <windows.h>
#include <iostream>
using namespace std;
int getpagesize();
void foo(void);
int change_page_permissions_of_address(void *addr);

int getpagesize() {
    SYSTEM_INFO si;
    GetSystemInfo(&si);
    return unsigned(si.dwPageSize);
}

void foo(void) {
    int i = 0;
    i++;
    printf("i: %d\n", i);
}

int change_page_permissions_of_address(void *addr) {
     // Get total function size
    int page_size = getpagesize();
    DWORD dwOldProtect;
    // Obtain the addresses for the functions so we can calculate size.
    uintptr_t tmp = (uintptr_t)addr-(uintptr_t)addr%page_size;
    addr = (void*)tmp;

     // We need to give ourselves access to modifify data at the given address
    if (VirtualProtect(addr, page_size, PAGE_EXECUTE_READWRITE, &dwOldProtect) == -1) {
        return -1;
    }

    return 0;
}

int main() {
    void *foo_addr = (void*)foo;
    if (change_page_permissions_of_address(foo_addr) == -1) {
        printf("Error while changing page permissions of foo(): %s\n");
        return 1;
    }

    // Call the unmodified foo()
    puts("Calling foo...");
    foo();

    // Change the immediate value in the addl instruction in foo() to 42
    unsigned char *instruction = (unsigned char*)foo_addr + 18;
    *instruction = 0x2A;

    puts("Calling foo..., but I am the self-modifying");
    foo();
    cin.get();
    return 0;
}
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
yesii_0691
  • 23
  • 7

1 Answers1

1

Check of VirtualProtect is incorrect as it returns FALSE, not -1 in case of an error. Also I suspect that you will need to obtain a pointer to a starting page of the region of pages that foo belongs to and it is not clear where did you get offset 18 from.

user7860670
  • 35,849
  • 4
  • 58
  • 84
  • what would it be a proper way to exit it? – yesii_0691 Apr 21 '19 at 05:56
  • @VTT `uintptr_t tmp = (uintptr_t)addr-(uintptr_t)addr%page_size` this aligns the address to the page bounday. – Ajay Brahmakshatriya Apr 21 '19 at 05:58
  • @AjayBrahmakshatriya Yes, but it is not enough, it must a starting page of the region. – user7860670 Apr 21 '19 at 05:58
  • 1
    My guess is OP's text section fits in a page. Because they don't get a SEGFAULT while writing to the address, my guess is that is not the reason. – Ajay Brahmakshatriya Apr 21 '19 at 06:01
  • @yesii_0691 you are following an article written for Linux. With Linux you are allowed to arbitrarily change permissions of pages even if they were a part of a bigger call to mmap. Windows doesn't allow you do that. What you would have to do is use `VirtualQuery` to identify the region your `foo` function is a part of and then modify the protections for that entire region. But my understanding is that is not the issue here. But you should fix this later when you are dealing with bigger functions and binaries. – Ajay Brahmakshatriya Apr 21 '19 at 06:08
  • that's why I changed mprotect for virtualprotect , but I dont see clearly the error why overwrite both on 1 – yesii_0691 Apr 21 '19 at 06:11
  • @yesii_0691 your offset (18) is most probably wrong because you just took the value from the article. You are overwriting something else with `0x42`. Maybe something beyond the actual function. – Ajay Brahmakshatriya Apr 21 '19 at 06:16