├── .gitmodules ├── README.md ├── capstone.h ├── main.c ├── make-linux.sh ├── make.sh ├── printf.h ├── stub.h ├── test_module └── tinyalloc.h /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "capstone"] 2 | path = capstone 3 | url = https://github.com/aquynh/capstone 4 | [submodule "printf"] 5 | path = printf 6 | url = https://github.com/mpaland/printf 7 | [submodule "tinyalloc"] 8 | path = tinyalloc 9 | url = https://github.com/thi-ng/tinyalloc 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Helper module for PongoKit 2 | 3 | ## Usage 4 | 5 | Using this module, the following 3 commands will be available in pongoOS shell: 6 | 7 | - mread: read DWORD from memory 8 | The syntax is ```mread 0xaaaaa```. The only supported input format is hex in lower case. Please also pay attention to the space, only one space is allowed 9 | The output will be a DWORD (little endian) 10 | - mwrite: write to memory 11 | The syntax is ```mwrite 0xaaaaaaaa f 0xbbbbbbbb```. 0xaaaaaaaa is the target addr to write, f is the writing width, and 0xbbbbbbbb is the value to be written. Addrs' format is same as above, and f can be b,w,d,q which refers to bytes, word, dword, qword. 12 | - dis: disassemble 13 | The symtax is ```dis 0xaaaaaaaa [0xbbb]```, 0xaaaa is the address to be disassembled; 0xbbbb is number of instructions to disassemble, which could be omitted. 14 | - mfind: Search memory 15 | Syntax: ```mfind 0xaaaaaaaa 0xbbbb 0xcccccccc 0xdddd``` 0xaaaaaaaa: start address, 0xbbbb: search length, 0xcccccc: pattern in uint64_t, 0xdddd: pattern length 16 | - dumpvars: Print pongoOS runtime variables 17 | - memmap: Dump out the memory-map in the device-tree 18 | - hexdump: Print hexdump of specified addr 19 | Syntax: ```hexdump 0xaaaaaaaa [0xbbbb]```, 0xaaaaaaaa is the address, 0xbbbb is dump length 20 | 21 | ## Build 22 | 23 | ``` 24 | $ git clone https://github.com/checkra1n/PongoKit 25 | $ cd PongoKit 26 | $ git clone --recursive https://github.com/NyaMisty/PongoHelper test 27 | $ cd test 28 | $ ./make.sh 29 | $ python ../scripts/module_load.py test_module 30 | ``` 31 | 32 | ## Run 33 | 34 | You should build first, but if you want a binary, you can find the built test_module in the repo 35 | 36 | ``` 37 | $ python ../scripts/module_load.py test_module 38 | $ python ../scripts/issue_cmd.py dumpvars 39 | ``` 40 | 41 | -------------------------------------------------------------------------------- /capstone.h: -------------------------------------------------------------------------------- 1 | #include "capstone/capstone.h" 2 | #ifdef USE_TA 3 | void* my_cs_malloc(size_t size) { 4 | stub_log("malloc %d\n", size); 5 | void *ret = ta_alloc(size); 6 | stub_log("malloc end"); 7 | return ret; 8 | } 9 | 10 | void* my_cs_calloc(size_t nmemb, size_t size) { 11 | stub_log("calloc: %x\n", nmemb * size); 12 | void *ret = ta_calloc(nmemb, size); 13 | stub_log("calloc_ret: %llx\n", ret); 14 | stub_log("calloc end\n"); 15 | return ret; 16 | } 17 | 18 | void* my_cs_realloc(void *ptr, size_t size){ 19 | stub_log("realloc %d\n", size); 20 | void *new = ta_alloc(size); 21 | memcpy(new, ptr, size); 22 | ta_free(ptr); 23 | stub_log("realloc end\n"); 24 | return new; 25 | } 26 | 27 | void my_cs_free(void *ptr) { 28 | stub_log("free\n"); 29 | //ta_free(ptr); 30 | //free(ptr); 31 | } 32 | 33 | int my_cs_vsnprintf(char *str, size_t size, const char *format, va_list ap){ 34 | stub_log("%s", format); 35 | return vsnprintf(str, size, format, ap); 36 | } 37 | #else 38 | void* my_cs_malloc(size_t size) { 39 | stub_log("malloc %d\n", size); 40 | //void *ret = ta_alloc(size); 41 | void *ret = malloc(size); 42 | stub_log("malloc end\n"); 43 | return ret; 44 | } 45 | 46 | void* my_cs_calloc(size_t nmemb, size_t size) { 47 | stub_log("calloc %d\n", nmemb * size); 48 | void *ret = malloc(nmemb * size); 49 | memset(ret, 0, nmemb * size); 50 | //void *ret = ta_calloc(nmemb, size); 51 | stub_log("calloc_ret: %llx\n", ret); 52 | stub_log("calloc end\n"); 53 | return ret; 54 | } 55 | 56 | void* my_cs_realloc(void *ptr, size_t size){ 57 | stub_log("realloc %d\n", size); 58 | //void *new = ta_alloc(size); 59 | void *new = malloc(size); 60 | memcpy(new, ptr, size); 61 | free(ptr); 62 | //ta_free(ptr); 63 | stub_log("realloc end\n"); 64 | return new; 65 | } 66 | 67 | void my_cs_free(void *ptr) { 68 | stub_log("free\n"); 69 | //ta_free(ptr); 70 | //free(ptr); 71 | } 72 | 73 | int my_cs_vsnprintf(char *str, size_t size, const char *format, va_list ap){ 74 | stub_log("%s", format); 75 | return vsnprintf(str, size, format, ap); 76 | } 77 | #endif 78 | #undef vsnprintf 79 | cs_opt_mem cs_mem_setup = { 80 | .malloc = my_cs_malloc, 81 | .calloc = my_cs_calloc, 82 | .realloc = my_cs_realloc, 83 | .free = my_cs_free, 84 | .vsnprintf_ = my_cs_vsnprintf, 85 | }; 86 | 87 | csh cs_handle; 88 | 89 | void setup_capstone() { 90 | printf("Set up cs_opt_mem\n", 0); 91 | cs_option(0, CS_OPT_MEM, &cs_mem_setup); 92 | 93 | printf("Starting to cs_open\n", 0); 94 | 95 | int ret = cs_open(CS_ARCH_ARM64, CS_MODE_ARM, &cs_handle); 96 | if (ret) { 97 | printf("ERROR: Failed to initialize engine!, err=%d\n", ret); 98 | return; 99 | } 100 | printf("Successfully initialized capstone engine\n", 0); 101 | cs_option(cs_handle, CS_OPT_SKIPDATA, CS_OPT_ON); 102 | printf("Set up skipdata\n", 0); 103 | } 104 | 105 | -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "printf.h" 4 | #include "stub.h" 5 | #include "capstone.h" 6 | #include "tinyalloc.h" 7 | 8 | void (*existing_preboot_hook)(); 9 | 10 | void m_preboot_hook() 11 | { 12 | command_puts("Called pre-boot hook"); 13 | printf("aaa: %d", existing_preboot_hook); 14 | command_puts("Resetting ramdisk_size to 0"); 15 | ramdisk_size = 0; 16 | command_puts("Kick off!"); 17 | for (long long i = 0; i < 3*1000*1000*1000LL; i++); 18 | 19 | /* Do patches here */ 20 | //if (existing_preboot_hook != NULL) 21 | // existing_preboot_hook(); 22 | return; 23 | } 24 | 25 | void print_addr(const char *str, uint64_t val) { 26 | printf("%s: %llx\n", str, val); 27 | } 28 | 29 | void dump_runtime_vars() { 30 | print_addr("loader_xfer_recv_data", loader_xfer_recv_data); 31 | print_addr("loader_xfer_recv_count", loader_xfer_recv_count); 32 | 33 | print_addr("gBootArgs", gBootArgs); 34 | printf(" .Revision: %d\n", gBootArgs->Revision); 35 | printf(" .Version: %d\n", gBootArgs->Version); 36 | print_addr(" .virtBase", gBootArgs->virtBase); 37 | print_addr(" .physBase", gBootArgs->physBase); 38 | print_addr(" .memSize", gBootArgs->memSize); 39 | print_addr(" .topOfKernelData", gBootArgs->topOfKernelData); 40 | printf(" .machineType: %d\n", gBootArgs->machineType); 41 | print_addr(" .CommandLine: ", &gBootArgs->CommandLine); 42 | print_addr(" .bootFlags", gBootArgs->bootFlags); 43 | print_addr(" .memSizeActual", gBootArgs->memSizeActual); 44 | 45 | print_addr("gEntryPoint", gEntryPoint); 46 | print_addr("gDeviceTree", gDeviceTree); 47 | print_addr("gDevType", gDevType); 48 | print_addr("ramdisk_buf", ramdisk_buf); 49 | print_addr("autoboot_count", autoboot_count); 50 | print_addr("existing_preboot_hook", existing_preboot_hook); 51 | } 52 | 53 | uint64_t get_hex_num(char *input) { 54 | if (input[0] != '0' || input[1] != 'x') 55 | return 0; 56 | uint64_t ret = 0, cur = 2; 57 | while (1) { 58 | char c = input[cur++]; 59 | if (!c) 60 | break; 61 | if (c >= '0' && c <= '9'){ 62 | c = c - '0'; 63 | } else if (c >= 'a' && c <= 'f') { 64 | c = c - 'a' + 10; 65 | } else { 66 | command_puts("Wrong format"); 67 | } 68 | ret *= 16; 69 | ret += c; 70 | } 71 | return ret; 72 | } 73 | 74 | void mem_read(const char *cmd, char *args) { 75 | uint64_t addr = get_hex_num(args); 76 | uint32_t data = *(uint32_t *)addr; 77 | printf("Read data: %08x\n", data); 78 | } 79 | 80 | void mem_write(const char *cmd, char *args) { 81 | char tempbuf[34]; 82 | int i = 0; char c = 0; 83 | while ((c = *args++) != ' ' && c != 0) { 84 | tempbuf[i++] = c; 85 | } 86 | if (c == 0){ 87 | command_puts(tempbuf); 88 | command_puts("mwrite target_addr width value"); 89 | return; 90 | } 91 | tempbuf[i] = 0; 92 | uint64_t target = get_hex_num(tempbuf); 93 | 94 | char width = *args++; 95 | if (width != 'b' && width != 'w' && width != 'd' && width != 'q') { 96 | printf("wrong width: %c", width); 97 | return; 98 | } 99 | 100 | args++; // eat space 101 | 102 | strcpy(tempbuf, args); 103 | uint64_t value = get_hex_num(tempbuf); 104 | 105 | printf("Writing to %x\n", target); 106 | printf("Width %c\n", width); 107 | printf("Value %x\n", value); 108 | switch(width) { 109 | case 'b': 110 | *(uint8_t *)target = value; 111 | break; 112 | case 'w': 113 | *(uint16_t *)target = value; 114 | break; 115 | case 'd': 116 | *(uint32_t *)target = value; 117 | break; 118 | case 'q': 119 | *(uint64_t *)target = value; 120 | break; 121 | } 122 | command_puts("write success"); 123 | } 124 | 125 | void disassemble(const char *cmd, char *args) { 126 | //setup_capstone(); 127 | char tempbuf[0x400]; 128 | int i = 0; char c = 0; 129 | while ((c = *args++) != ' ' && c != 0) { 130 | tempbuf[i++] = c; 131 | } 132 | tempbuf[i] = 0; 133 | uint64_t addr = get_hex_num(tempbuf); 134 | print_addr("Going to disassemble", addr); 135 | 136 | uint64_t len = 20; 137 | if (c != 0) { 138 | strcpy(tempbuf, args); 139 | printf("%s", args); 140 | len = get_hex_num(tempbuf); 141 | } 142 | print_addr("Disassemble len", len); 143 | 144 | memcpy(tempbuf, addr, len * 4); 145 | cs_insn* insn; 146 | size_t count = cs_disasm(cs_handle, (unsigned char*)tempbuf, len * 4, addr, 0, &insn); 147 | printf("Got %d ins\n", count); 148 | if (count) { 149 | size_t j; 150 | for (j = 0; j < count; j++) { 151 | printf("0x%llx ", insn[j].address); 152 | for (int off = 0; off < insn[j].size; off++){ 153 | printf("%02X ", insn[j].bytes[off]); 154 | } 155 | printf("\t%s\t\t%s\n", insn[j].mnemonic, insn[j].op_str); 156 | /*printf("0x%llx:\t%s\t\t%s\n", 157 | insn[j].address, insn[j].mnemonic, insn[j].op_str);*/ 158 | } 159 | 160 | cs_free(insn, count); 161 | } 162 | printf("Disassembled %d instruction\n", count); 163 | } 164 | 165 | void memfind(const char *cmd, char *args) { 166 | char tempbuf[0x400]; 167 | int i = 0; char c = 0; 168 | while ((c = *args++) != ' ' && c != 0) { 169 | tempbuf[i++] = c; 170 | } 171 | tempbuf[i] = 0; 172 | uint64_t addr = get_hex_num(tempbuf); 173 | if (c == 0) { 174 | printf("Wrong usage1\n"); 175 | return; 176 | } 177 | printf("Got target addr: 0x%llx\n", addr); 178 | 179 | i = 0; 180 | while ((c = *args++) != ' ' && c != 0) { 181 | tempbuf[i++] = c; 182 | } 183 | tempbuf[i] = 0; 184 | uint64_t len = get_hex_num(tempbuf); 185 | if (c == 0) { 186 | printf("Wrong usage2\n"); 187 | return; 188 | } 189 | printf("Got len: 0x%llx\n", len); 190 | 191 | i = 0; 192 | while ((c = *args++) != ' ' && c != 0) { 193 | tempbuf[i++] = c; 194 | } 195 | tempbuf[i] = 0; 196 | uint64_t _pattern = get_hex_num(tempbuf); 197 | char *pattern = (char *)&_pattern; 198 | if (c == 0) { 199 | printf("Wrong usage3\n"); 200 | return; 201 | } 202 | printf("Got pattern: 0x%llx\n", _pattern); 203 | 204 | i = 0; 205 | while ((c = *args++) != ' ' && c != 0) { 206 | tempbuf[i++] = c; 207 | } 208 | tempbuf[i] = 0; 209 | uint64_t pattern_size = get_hex_num(tempbuf); 210 | printf("Got pattern size: 0x%llx\n", pattern_size); 211 | 212 | uint64_t curaddr = addr; 213 | while (curaddr < addr + len) { 214 | //printf("Searching pattern from %llx\n", curaddr); 215 | memcpy(tempbuf, curaddr, sizeof(tempbuf)); 216 | for (int i = 0; i < sizeof(tempbuf) - pattern_size; i++) { 217 | for (int c = 0; c < pattern_size; c++) { 218 | if (tempbuf[i + c] != pattern[c]) { 219 | goto notgood; 220 | } 221 | } 222 | printf("Found pattern at address 0x%llx\n", curaddr + c); 223 | return; 224 | notgood: 225 | continue; 226 | } 227 | curaddr += (sizeof(tempbuf) - pattern_size) & ~0xf; 228 | } 229 | printf("Pattern not found\n"); 230 | } 231 | 232 | int prop_callback(dt_find_cb_t *userarg, dt_node_t *node, int level, const char *name, void *val, uint32_t length) { 233 | if (strcmp(name, "name") == 0) { 234 | printf("propcallback: node: %llx level: %d name: %s val: %llx length: %d\n", node, level, name, val, length); 235 | printf("curnode_name: %s\n", val); 236 | if (strcmp(val, userarg->name) == 0){ 237 | 238 | printf("Found target node!\n"); 239 | userarg->node = node; 240 | return 1; 241 | } 242 | } 243 | return 0; 244 | } 245 | 246 | extern dt_node_t *memmap = NULL; 247 | 248 | void find_memmap() { 249 | dt_find_cb_t tempbuf; 250 | tempbuf.name = "memory-map"; 251 | tempbuf.node = NULL; 252 | printf("Passing %llx as custom arg\n", tempbuf); 253 | dt_parse(gDeviceTree, 0, NULL, NULL, NULL, prop_callback, &tempbuf); 254 | if (!tempbuf.node) { 255 | printf("Failed to find memmap\n"); 256 | } 257 | printf("Found memmap at %llx\n", tempbuf.node); 258 | memmap = tempbuf.node; 259 | } 260 | 261 | void print_memmap(){ 262 | if (!memmap) { 263 | find_memmap(); 264 | } 265 | int i = 0, off = 0; 266 | while(i++ < memmap->nprop) { 267 | dt_prop_t *prop = &memmap->prop[off]; 268 | 269 | if (prop->len == 16){ 270 | // memmap entry 271 | struct memmap *curentry = prop->val; 272 | printf("prop key: %s, len: %d, addr: %llx, memsize: %llx\n", prop->key, prop->len, curentry->addr, curentry->size); 273 | } else if (prop->len == 4) { 274 | // DWORD entry 275 | printf("prop key: %s, len: %d, val: %d\n", prop->key, prop->len, *(uint32_t *)prop->val); 276 | } else { 277 | // string entry 278 | printf("prop key: %s, len: %d, val: %s\n", prop->key, prop->len, prop->val); 279 | } 280 | 281 | //off += DT_KEY_LEN + 4 + prop->len; 282 | off += (((prop->len & 0xFFFFFF) + 3) & 0x1FFFFFC) + 36; 283 | } 284 | } 285 | 286 | #define HEXDUMP_COLS 8 287 | // from https://gist.github.com/richinseattle/c527a3acb6f152796a580401057c78b4 288 | void _hexdump(void *mem, unsigned int len) 289 | { 290 | unsigned int i, j; 291 | 292 | for(i = 0; i < len + ((len % HEXDUMP_COLS) ? (HEXDUMP_COLS - len % HEXDUMP_COLS) : 0); i++) 293 | { 294 | /* print offset */ 295 | if(i % HEXDUMP_COLS == 0) 296 | { 297 | printf("0x%06x: ", i); 298 | } 299 | 300 | /* print hex data */ 301 | if(i < len) 302 | { 303 | printf("%02x ", 0xFF & ((char*)mem)[i]); 304 | } 305 | else /* end of block, just aligning for ASCII dump */ 306 | { 307 | printf(" "); 308 | } 309 | 310 | /* print ASCII dump */ 311 | if(i % HEXDUMP_COLS == (HEXDUMP_COLS - 1)) 312 | { 313 | for(j = i - (HEXDUMP_COLS - 1); j <= i; j++) 314 | { 315 | if(j >= len) /* end of block, not really printing */ 316 | { 317 | putchar(' '); 318 | } 319 | else if(isprint(((char*)mem)[j])) /* printable char */ 320 | { 321 | putchar(0xFF & ((char*)mem)[j]); 322 | } 323 | else /* other char */ 324 | { 325 | putchar('.'); 326 | } 327 | } 328 | putchar('\n'); 329 | } 330 | } 331 | } 332 | 333 | void hexdump(const char *cmd, char *args) { 334 | char tempbuf[0x400]; 335 | int i = 0; char c = 0; 336 | while ((c = *args++) != ' ' && c != 0) { 337 | tempbuf[i++] = c; 338 | } 339 | tempbuf[i] = 0; 340 | uint64_t addr = get_hex_num(tempbuf); 341 | print_addr("Going to dump", addr); 342 | 343 | uint64_t len = 48; 344 | if (c != 0) { 345 | strcpy(tempbuf, args); 346 | printf("%s", args); 347 | len = get_hex_num(tempbuf); 348 | } 349 | print_addr("Dump len", len); 350 | _hexdump(addr, len); 351 | } 352 | 353 | void module_entry() { 354 | printf("Got preboot_hook: 0x%llx\n", preboot_hook); 355 | existing_preboot_hook = preboot_hook; 356 | preboot_hook = m_preboot_hook; 357 | 358 | printf("Dumping runtime vars...\n"); 359 | dump_runtime_vars(); 360 | 361 | init_ta(); 362 | 363 | setup_capstone(); 364 | 365 | find_memmap(); 366 | 367 | command_register("mread", "Read memory", mem_read); 368 | command_register("mwrite", "Write memory", mem_write); 369 | command_register("mfind", "Search memory", memfind); 370 | command_register("dis", "Disassemble memory", disassemble); 371 | command_register("dumpvars", "Dump runtime vars", dump_runtime_vars); 372 | command_register("memmap", "Print memmap", print_memmap); 373 | command_register("hexdump", "Hexdump", hexdump); 374 | } 375 | 376 | char* module_name = "test_module"; 377 | 378 | struct pongo_exports exported_symbols[] = { 379 | }; 380 | 381 | -------------------------------------------------------------------------------- /make-linux.sh: -------------------------------------------------------------------------------- 1 | cd "$(dirname $0)" 2 | arm64-apple-ios12.0.0-clang main.c -o test_module -arch arm64 -Xlinker -kext -nostdlib -Xlinker -fatal_warnings -I../include/ -D_SECURE__STRING_H_ -O3 3 | -------------------------------------------------------------------------------- /make.sh: -------------------------------------------------------------------------------- 1 | cd "$(dirname $0)" 2 | 3 | pushd capstone 4 | IOS_CC="xcrun -sdk iphoneos gcc" 5 | IOS_CFLAGS="-O2 -nostdlib -arch arm64" 6 | IOS_LDFLAGS="-arch arm64" 7 | IOS_ARCHS="arm64" 8 | CC="$IOS_CC" LIBARCHS="$IOS_ARCHS" CFLAGS="$IOS_CFLAGS" LDFLAGS="$IOS_LDFLAGS" MACOS_UNIVERSAL=no CAPSTONE_BUILD_CORE_ONLY=yes CAPSTONE_SHARED=no CAPSTONE_STATIC=yes CAPSTONE_ARCHS="arm aarch64" CAPSTONE_USE_SYS_DYN_MEM=no CAPSTONE_DIET=no make 9 | popd 10 | 11 | #SOURCE="printf/printf.c tinyalloc/tinyalloc.c main.c" 12 | SOURCE="printf/printf.c main.c" 13 | 14 | INCLUDE="-I../include -Icapstone/include" 15 | CC="xcrun -sdk iphoneos gcc" 16 | CFLAGS="-Wno-int-conversion -arch arm64 -Xlinker -kext -nostdlib -Xlinker -fatal_warnings" 17 | LDFLAGS="-static -Lcapstone/ -lcapstone" 18 | $CC $SOURCE -o test_module $CFLAGS $INCLUDE $LDFLAGS -D_SECURE__STRING_H_ -O3 19 | 20 | -------------------------------------------------------------------------------- /printf.h: -------------------------------------------------------------------------------- 1 | #include "printf/printf.h" 2 | /*#define _vsnprintf vsnprintf 3 | #undef vsnprintf 4 | extern int vsnprintf (char * s, size_t n, const char * format, va_list arg ) { 5 | return _vsnprintf(s, n, format, arg); 6 | }*/ 7 | 8 | // for our printf 9 | void _putchar(char c) { 10 | printf32("%c", c); 11 | } 12 | -------------------------------------------------------------------------------- /stub.h: -------------------------------------------------------------------------------- 1 | #ifdef DEBUG_STUB_CALL 2 | #define stub_log printf 3 | #else 4 | void stub_log(const char *a, ...){ 5 | return; 6 | } 7 | #endif 8 | 9 | int putchar(int c) { 10 | printf32("%c", c); 11 | return c; 12 | } 13 | 14 | int isprint(int c){ 15 | return c >= 32 && c < 127; 16 | } 17 | 18 | int __tolower(int c) { 19 | if (c >= 'A' && c <= 'Z') { 20 | c -= 'A' - 'a'; 21 | } 22 | return c; 23 | } 24 | 25 | #undef memcpy 26 | void *my_memcpy(void *dst, const void *src, size_t size); 27 | extern void *memcpy(void *dst, const void *src, size_t size) { 28 | return my_memcpy(dst, src, size); 29 | } 30 | #define memcpy my_memcpy 31 | extern void *my_memcpy(void *dst, const void *src, size_t size) { 32 | for (size_t i = 0; i < size; i++) { 33 | ((char *)dst)[i] = ((char *)src)[i]; 34 | } 35 | return dst; 36 | } 37 | 38 | #undef bzero 39 | extern void bzero(void *s, size_t n){ 40 | memset(s, 0, n); 41 | } 42 | 43 | #undef strcmp 44 | int my_strcmp(const char *str1, const char *str2); 45 | extern int strcmp(const char *str1, const char *str2) { 46 | return my_strcmp(str1, str2); 47 | } 48 | #define strcmp my_strcmp 49 | extern int my_strcmp(const char *str1, const char *str2) 50 | { 51 | size_t i; 52 | 53 | for(i = 0; str1[i] == str2[i] && str1[i] && str2[i] ; ++i) 54 | ; 55 | return str1[i] - str2[i]; 56 | } 57 | 58 | #undef strlen 59 | size_t my_strlen(const char *str); 60 | extern size_t strlen(const char *str) { 61 | return my_strlen(str); 62 | } 63 | #define strlen my_strlen 64 | extern size_t my_strlen(const char *str) 65 | { 66 | size_t i; 67 | 68 | for(i = 0; str[i] ; ++i) 69 | ; 70 | return i; 71 | } 72 | 73 | #undef strcpy 74 | char *my_strcpy(char *dest, const char *src); 75 | extern char *strcpy(char *dest, const char *src) { 76 | return my_strcpy(dest, src); 77 | } 78 | #define strcpy my_strcpy 79 | extern char *my_strcpy(char *dest, const char *src) 80 | { 81 | size_t i; 82 | 83 | for(i = 0; src[i] ; ++i) 84 | dest[i] = src[i]; 85 | dest[i] = '\0'; 86 | return dest; 87 | } 88 | 89 | 90 | #undef strncmp 91 | int my_strncmp( const char * str1, const char * str2, size_t num ); 92 | extern int strncmp( const char * str1, const char * str2, size_t num ) { 93 | return my_strncmp(str1, str2, num); 94 | } 95 | #define strncmp my_strncmp 96 | extern int my_strncmp( const char * str1, const char * str2, size_t num ){ 97 | stub_log("strncmp called\n"); 98 | while (1) { 99 | char c1 = *str1++; 100 | char c2 = *str2++; 101 | if (c1 != c2) { 102 | if (c1 < c2){ 103 | stub_log("strncmp called\n"); 104 | return -1; 105 | } 106 | if (c1 > c2) { 107 | stub_log("strncmp called\n"); 108 | return 1; 109 | } 110 | } 111 | if (c1 == 0) 112 | break; 113 | } 114 | stub_log("strncmp end\n"); 115 | return 0; 116 | } 117 | 118 | #undef strncpy 119 | char* my_strncpy(char* destination, const char* source, size_t num); 120 | extern char* strncpy(char* destination, const char* source, size_t num) { 121 | return my_strncpy(destination, source, num); 122 | } 123 | #define strncpy my_strncpy 124 | extern char* my_strncpy(char* destination, const char* source, size_t num) 125 | { 126 | stub_log("strncpy s\n"); 127 | // return if no memory is allocated to the destination 128 | if (destination == NULL) 129 | return NULL; 130 | 131 | // take a pointer pointing to the beginning of destination string 132 | char* ptr = destination; 133 | 134 | // copy first num characters of C-string pointed by source 135 | // into the array pointed by destination 136 | while (*source && num--) 137 | { 138 | *destination = *source; 139 | destination++; 140 | source++; 141 | } 142 | 143 | // null terminate destination string 144 | *destination = '\0'; 145 | 146 | // destination is returned by standard strncpy() 147 | stub_log("strncpy e\n"); 148 | return ptr; 149 | } 150 | 151 | #undef strrchr 152 | char *my_strrchr(const char *str, int c); 153 | extern char *strrchr(const char *str, int c) { 154 | return my_strrchr(str, c); 155 | } 156 | #define strrchr my_strrchr 157 | extern char *my_strrchr(const char *str, int c) 158 | { 159 | stub_log("strncmp s\n"); 160 | char *p = NULL; 161 | 162 | for(; *str ; ++str) 163 | { 164 | if(*str == c) 165 | p = (char*) str; 166 | } 167 | stub_log("strncmp end\n"); 168 | return p; 169 | } 170 | 171 | #undef strstr 172 | char *my_strstr(const char *haystack, const char *needle); 173 | extern char *strstr(const char *haystack, const char *needle) { 174 | return my_strstr(haystack, needle); 175 | } 176 | #define strstr my_strstr 177 | extern char *my_strstr(const char *haystack, const char *needle) 178 | { 179 | stub_log("strstr s\n"); 180 | size_t n = strlen(needle); 181 | for(; *haystack ; ++haystack) 182 | { 183 | if(strncmp(haystack, needle, n) == 0){ 184 | stub_log("strstr e\n"); 185 | return (char *) haystack; 186 | } 187 | } 188 | stub_log("strstr e\n"); 189 | return 0; 190 | } 191 | 192 | #undef memset 193 | void *my_memset(void *dst, int val, size_t size); 194 | extern void *memset(void *dst, int val, size_t size) { 195 | return my_memset(dst, val, size); 196 | } 197 | #define memset my_memset 198 | extern void *my_memset(void *dst, int val, size_t size) { 199 | stub_log("memset s\n"); 200 | stub_log("size: %d\n", size); 201 | int i = 0; 202 | while (i < size){ 203 | if (size - i >= 4) { 204 | ((uint32_t *)dst)[i] = val; 205 | i += 4; 206 | } else if (size - i >= 2) { 207 | ((uint16_t *)dst)[i] = val; 208 | i += 2; 209 | } else { 210 | ((uint8_t *)dst)[i] = val; 211 | i += 1; 212 | } 213 | /*if (!(i % 128)) { 214 | stub_log("cur: %d\n", i); 215 | }*/ 216 | } 217 | stub_log("memset e\n"); 218 | return dst; 219 | } 220 | 221 | 222 | #undef memmove 223 | void *my_memmove(void *pvDst, const void *pvSrc, size_t n); 224 | extern void *memmove(void *pvDst, const void *pvSrc, size_t n) { 225 | return my_memmove(pvDst, pvSrc, n); 226 | } 227 | #define memmove my_memmove 228 | extern void *my_memmove(void *pvDst, const void *pvSrc, size_t n) { 229 | stub_log("memmove s\n"); 230 | unsigned char u8CopyByte=1; //flag bit 231 | char *pcSource =(char *)pvSrc; 232 | char *pcDstn =(char *)pvDst; 233 | 234 | if(pcSource == pcDstn) { //Source & destination have same address 235 | u8CopyByte=0; 236 | } else if(pcSource < pcDstn && pcDstn < pcSource + n) { // overlap 237 | /* If overlap then copy from end*/ 238 | pcSource += n; 239 | pcDstn += n; 240 | } 241 | if(u8CopyByte) { 242 | while(n--) 243 | *--pcDstn = *--pcSource; 244 | } 245 | 246 | stub_log("memmove s\n"); 247 | return pvDst; 248 | } 249 | -------------------------------------------------------------------------------- /test_module: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NyaMisty/PongoHelper/85b1a5cf43a92d0efd3fabc6519a2e6e8520256b/test_module -------------------------------------------------------------------------------- /tinyalloc.h: -------------------------------------------------------------------------------- 1 | #ifdef USE_TA 2 | //#define TA_DEBUG 3 | #include "tinyalloc/tinyalloc.h" 4 | #ifdef TA_DEBUG 5 | void print_s(char *input) { 6 | command_puts(input); 7 | } 8 | void print_i(size_t input) { 9 | printf("%d", input); 10 | } 11 | #endif 12 | void init_ta() { 13 | void *malloc_test = malloc(0x8000); 14 | ((uint64_t *)malloc_test)[0] = 0; 15 | print_addr("malloc_test", malloc_test); 16 | memset(malloc_test, 0, 0x8000); 17 | //uint64_t heapstart = loader_xfer_recv_data + 0x100000; 18 | //uint64_t heapend = heapstart + 0x80000; 19 | //memset(heapstart, 0, heapend - heapstart); 20 | printf("ta_init: %d\n", ta_init(malloc_test, malloc_test + 0x8000, 128, 16, 8)); 21 | printf("ta_check: %d\n", ta_check()); 22 | void *test = ta_alloc(10); 23 | print_addr("ta_alloc(10)", test); 24 | test = ta_calloc(1, 200); 25 | print_addr("ta_calloc(200)", test); 26 | printf("ta_check: %d\n", ta_check()); 27 | } 28 | #else 29 | void init_ta(){ 30 | 31 | } 32 | #endif 33 | --------------------------------------------------------------------------------