Skip to content

Instantly share code, notes, and snippets.

@nkoneko
Created January 20, 2021 18:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nkoneko/d19c94f6911f73cffb2e7c71b80a217b to your computer and use it in GitHub Desktop.
Save nkoneko/d19c94f6911f73cffb2e7c71b80a217b to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <mach/port.h>
#include <mach/mach.h>
#include <mach/vm_region.h>
#include <mach/vm_map.h>
#include <chrono>
#include <thread>
#include <utility>
#include <vector>
#include <memory>
namespace {
std::vector<std::pair<uint64_t, uint64_t>> ranges;
std::vector<uint64_t> addresses;
void find_regions(task_t task) {
vm_size_t size = 0;
vm_address_t address = 0;
struct vm_region_submap_info info;
uint32_t infoCount = VM_REGION_SUBMAP_INFO_COUNT;
uint32_t nesting_depth;
while (!vm_region_recurse_64(task, &address, &size, &nesting_depth, (vm_region_recurse_info_t) &info, &infoCount)) {
if (info.is_submap) {
nesting_depth++;
} else {
if ((info.protection & (VM_PROT_WRITE | VM_PROT_READ)) == 3 && (info.max_protection & (VM_PROT_WRITE | VM_PROT_READ)) == 3) {
ranges.push_back(std::make_pair(address, address + size));
}
address += size;
}
}
}
void search(task_t task, int value) {
for (auto& [start, end] : ranges) {
uint64_t size = end - start;
vm_size_t outsize;
uint64_t page_address = start & 0xFFFFFFFFFFFFF000ul;
std::unique_ptr<uint8_t[]> buffer(new uint8_t[size]);
kern_return_t kret = vm_read_overwrite(task, page_address, size, (vm_address_t) buffer.get(), &outsize);
if (kret) {
fprintf(stderr, "failed to vm_read. %s\n", mach_error_string(kret));
}
if (!outsize) {
fprintf(stderr, "failed to read\n");
}
for (size_t i = 0; i < size; i += sizeof(int)) {
int *p = reinterpret_cast<int*>(buffer.get() + i);
if (*p == value) {
addresses.push_back(reinterpret_cast<uint64_t>(page_address + i));
}
}
}
}
void filter(task_t task, int value) {
std::vector<uint64_t> new_addresses;
for (auto& addr : addresses) {
auto pageAddr = addr & 0xFFFFFFFFFFFFF000ul;
auto offset = addr - pageAddr;
vm_size_t outsize;
std::unique_ptr<uint8_t[]> buffer(new uint8_t[offset + sizeof(int)]);
kern_return_t kret = vm_read_overwrite(task, pageAddr, offset + sizeof(int), (vm_address_t) buffer.get(), &outsize);
if (kret) {
fprintf(stderr, "failed to vm_read (filter). %s\n", mach_error_string(kret));
}
auto* p = reinterpret_cast<int*>((buffer.get() + offset));
if (*p == value) {
new_addresses.push_back(addr);
}
}
addresses = new_addresses;
}
}
int main(int argc, char *argv[]) {
pid_t pid;
if (pid = fork()) {
printf("child pid=%d\n", pid);
for (int i = 0; i < 20; i++) {
printf("Parent: %d\n", i);
std::this_thread::sleep_for(std::chrono::seconds(1));
}
} else {
pid_t ppid = getppid();
printf("parent pid=%d\n", ppid);
std::this_thread::sleep_for(std::chrono::seconds(5));
printf("Child\n");
task_t task;
kern_return_t kret;
kret = task_for_pid(mach_task_self(), ppid, &task);
if (kret) {
fprintf(stderr, "failed to task_for_pid. %s\n", mach_error_string(kret));
return 1;
}
kret = task_suspend(task);
if (kret) {
fprintf(stderr, "failed to suspend. %s\n", mach_error_string(kret));
return 1;
}
find_regions(task);
search(task, 4);
std::this_thread::sleep_for(std::chrono::seconds(5));
kret = task_resume(task);
if (kret) {
fprintf(stderr, "failed to resume. %s\n", mach_error_string(kret));
return 1;
}
printf("resumed\n");
std::this_thread::sleep_for(std::chrono::seconds(5));
printf("nine?\n");
kret = task_suspend(task);
if (kret) {
fprintf(stderr, "failed to suspend. %s\n", mach_error_string(kret));
return 1;
}
filter(task, 9);
printf("found %lu addresses.\n", addresses.size());
printf("overwriting...\n");
int value = 3;
for (auto& addr : addresses) {
kret = vm_write(task, (vm_address_t) addr, (pointer_t) &value, sizeof(int));
}
kret = task_resume(task);
if (kret) {
fprintf(stderr, "failed to resume. %s\n", mach_error_string(kret));
return 1;
}
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment