├── .gitignore ├── README.md ├── get_aslr.xcodeproj ├── project.pbxproj └── project.xcworkspace │ └── contents.xcworkspacedata └── get_aslr ├── Attach.c ├── Attach.h └── main.c /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | .DS_Store 3 | */build/* 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | xcuserdata 13 | profile 14 | *.moved-aside 15 | DerivedData 16 | .idea/ 17 | *.hmap 18 | *.xccheckout 19 | 20 | #CocoaPods 21 | Pods -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | get_aslr 2 | ======== 3 | 4 | This is basically a wrapper around fG!'s [MachOView fork](https://github.com/gdbinit/MachOView). 5 | 6 | Usage 7 | ----- 8 | ``` 9 | $ sudo get_aslr $(pgrep Calculator) 10 | ASLR slide: 0x1787000 11 | ``` 12 | -------------------------------------------------------------------------------- /get_aslr.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 5529514D18AEF6EF0086301E /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = 5529514C18AEF6EF0086301E /* main.c */; }; 11 | 55D4081E18AF128F001E73F7 /* Attach.c in Sources */ = {isa = PBXBuildFile; fileRef = 55D4081C18AF128F001E73F7 /* Attach.c */; }; 12 | /* End PBXBuildFile section */ 13 | 14 | /* Begin PBXCopyFilesBuildPhase section */ 15 | 5529514718AEF6EF0086301E /* CopyFiles */ = { 16 | isa = PBXCopyFilesBuildPhase; 17 | buildActionMask = 2147483647; 18 | dstPath = /usr/share/man/man1/; 19 | dstSubfolderSpec = 0; 20 | files = ( 21 | ); 22 | runOnlyForDeploymentPostprocessing = 1; 23 | }; 24 | /* End PBXCopyFilesBuildPhase section */ 25 | 26 | /* Begin PBXFileReference section */ 27 | 5529514918AEF6EF0086301E /* get_aslr */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = get_aslr; sourceTree = BUILT_PRODUCTS_DIR; }; 28 | 5529514C18AEF6EF0086301E /* main.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = ""; }; 29 | 55D4081C18AF128F001E73F7 /* Attach.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = Attach.c; sourceTree = ""; }; 30 | 55D4081D18AF128F001E73F7 /* Attach.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Attach.h; sourceTree = ""; }; 31 | /* End PBXFileReference section */ 32 | 33 | /* Begin PBXFrameworksBuildPhase section */ 34 | 5529514618AEF6EF0086301E /* Frameworks */ = { 35 | isa = PBXFrameworksBuildPhase; 36 | buildActionMask = 2147483647; 37 | files = ( 38 | ); 39 | runOnlyForDeploymentPostprocessing = 0; 40 | }; 41 | /* End PBXFrameworksBuildPhase section */ 42 | 43 | /* Begin PBXGroup section */ 44 | 5529514018AEF6EF0086301E = { 45 | isa = PBXGroup; 46 | children = ( 47 | 5529514B18AEF6EF0086301E /* get_aslr */, 48 | 5529514A18AEF6EF0086301E /* Products */, 49 | ); 50 | sourceTree = ""; 51 | }; 52 | 5529514A18AEF6EF0086301E /* Products */ = { 53 | isa = PBXGroup; 54 | children = ( 55 | 5529514918AEF6EF0086301E /* get_aslr */, 56 | ); 57 | name = Products; 58 | sourceTree = ""; 59 | }; 60 | 5529514B18AEF6EF0086301E /* get_aslr */ = { 61 | isa = PBXGroup; 62 | children = ( 63 | 5529514C18AEF6EF0086301E /* main.c */, 64 | 55D4081C18AF128F001E73F7 /* Attach.c */, 65 | 55D4081D18AF128F001E73F7 /* Attach.h */, 66 | ); 67 | path = get_aslr; 68 | sourceTree = ""; 69 | }; 70 | /* End PBXGroup section */ 71 | 72 | /* Begin PBXNativeTarget section */ 73 | 5529514818AEF6EF0086301E /* get_aslr */ = { 74 | isa = PBXNativeTarget; 75 | buildConfigurationList = 5529515218AEF6EF0086301E /* Build configuration list for PBXNativeTarget "get_aslr" */; 76 | buildPhases = ( 77 | 5529514518AEF6EF0086301E /* Sources */, 78 | 5529514618AEF6EF0086301E /* Frameworks */, 79 | 5529514718AEF6EF0086301E /* CopyFiles */, 80 | ); 81 | buildRules = ( 82 | ); 83 | dependencies = ( 84 | ); 85 | name = get_aslr; 86 | productName = get_aslr; 87 | productReference = 5529514918AEF6EF0086301E /* get_aslr */; 88 | productType = "com.apple.product-type.tool"; 89 | }; 90 | /* End PBXNativeTarget section */ 91 | 92 | /* Begin PBXProject section */ 93 | 5529514118AEF6EF0086301E /* Project object */ = { 94 | isa = PBXProject; 95 | attributes = { 96 | LastUpgradeCheck = 0500; 97 | ORGANIZATIONNAME = Tyilo; 98 | }; 99 | buildConfigurationList = 5529514418AEF6EF0086301E /* Build configuration list for PBXProject "get_aslr" */; 100 | compatibilityVersion = "Xcode 3.2"; 101 | developmentRegion = English; 102 | hasScannedForEncodings = 0; 103 | knownRegions = ( 104 | en, 105 | ); 106 | mainGroup = 5529514018AEF6EF0086301E; 107 | productRefGroup = 5529514A18AEF6EF0086301E /* Products */; 108 | projectDirPath = ""; 109 | projectRoot = ""; 110 | targets = ( 111 | 5529514818AEF6EF0086301E /* get_aslr */, 112 | ); 113 | }; 114 | /* End PBXProject section */ 115 | 116 | /* Begin PBXSourcesBuildPhase section */ 117 | 5529514518AEF6EF0086301E /* Sources */ = { 118 | isa = PBXSourcesBuildPhase; 119 | buildActionMask = 2147483647; 120 | files = ( 121 | 55D4081E18AF128F001E73F7 /* Attach.c in Sources */, 122 | 5529514D18AEF6EF0086301E /* main.c in Sources */, 123 | ); 124 | runOnlyForDeploymentPostprocessing = 0; 125 | }; 126 | /* End PBXSourcesBuildPhase section */ 127 | 128 | /* Begin XCBuildConfiguration section */ 129 | 5529515018AEF6EF0086301E /* Debug */ = { 130 | isa = XCBuildConfiguration; 131 | buildSettings = { 132 | ALWAYS_SEARCH_USER_PATHS = NO; 133 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 134 | CLANG_CXX_LIBRARY = "libc++"; 135 | CLANG_ENABLE_OBJC_ARC = YES; 136 | CLANG_WARN_BOOL_CONVERSION = YES; 137 | CLANG_WARN_CONSTANT_CONVERSION = YES; 138 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 139 | CLANG_WARN_EMPTY_BODY = YES; 140 | CLANG_WARN_ENUM_CONVERSION = YES; 141 | CLANG_WARN_INT_CONVERSION = YES; 142 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 143 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 144 | COPY_PHASE_STRIP = NO; 145 | GCC_C_LANGUAGE_STANDARD = gnu99; 146 | GCC_DYNAMIC_NO_PIC = NO; 147 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 148 | GCC_OPTIMIZATION_LEVEL = 0; 149 | GCC_PREPROCESSOR_DEFINITIONS = ( 150 | "DEBUG=1", 151 | "$(inherited)", 152 | ); 153 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 154 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 155 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 156 | GCC_WARN_UNDECLARED_SELECTOR = YES; 157 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 158 | GCC_WARN_UNUSED_FUNCTION = YES; 159 | GCC_WARN_UNUSED_VARIABLE = YES; 160 | MACOSX_DEPLOYMENT_TARGET = 10.9; 161 | ONLY_ACTIVE_ARCH = YES; 162 | SDKROOT = macosx; 163 | }; 164 | name = Debug; 165 | }; 166 | 5529515118AEF6EF0086301E /* Release */ = { 167 | isa = XCBuildConfiguration; 168 | buildSettings = { 169 | ALWAYS_SEARCH_USER_PATHS = NO; 170 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 171 | CLANG_CXX_LIBRARY = "libc++"; 172 | CLANG_ENABLE_OBJC_ARC = YES; 173 | CLANG_WARN_BOOL_CONVERSION = YES; 174 | CLANG_WARN_CONSTANT_CONVERSION = YES; 175 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 176 | CLANG_WARN_EMPTY_BODY = YES; 177 | CLANG_WARN_ENUM_CONVERSION = YES; 178 | CLANG_WARN_INT_CONVERSION = YES; 179 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 180 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 181 | COPY_PHASE_STRIP = YES; 182 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 183 | ENABLE_NS_ASSERTIONS = NO; 184 | GCC_C_LANGUAGE_STANDARD = gnu99; 185 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 186 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 187 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 188 | GCC_WARN_UNDECLARED_SELECTOR = YES; 189 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 190 | GCC_WARN_UNUSED_FUNCTION = YES; 191 | GCC_WARN_UNUSED_VARIABLE = YES; 192 | MACOSX_DEPLOYMENT_TARGET = 10.9; 193 | SDKROOT = macosx; 194 | }; 195 | name = Release; 196 | }; 197 | 5529515318AEF6EF0086301E /* Debug */ = { 198 | isa = XCBuildConfiguration; 199 | buildSettings = { 200 | PRODUCT_NAME = "$(TARGET_NAME)"; 201 | }; 202 | name = Debug; 203 | }; 204 | 5529515418AEF6EF0086301E /* Release */ = { 205 | isa = XCBuildConfiguration; 206 | buildSettings = { 207 | PRODUCT_NAME = "$(TARGET_NAME)"; 208 | }; 209 | name = Release; 210 | }; 211 | /* End XCBuildConfiguration section */ 212 | 213 | /* Begin XCConfigurationList section */ 214 | 5529514418AEF6EF0086301E /* Build configuration list for PBXProject "get_aslr" */ = { 215 | isa = XCConfigurationList; 216 | buildConfigurations = ( 217 | 5529515018AEF6EF0086301E /* Debug */, 218 | 5529515118AEF6EF0086301E /* Release */, 219 | ); 220 | defaultConfigurationIsVisible = 0; 221 | defaultConfigurationName = Release; 222 | }; 223 | 5529515218AEF6EF0086301E /* Build configuration list for PBXNativeTarget "get_aslr" */ = { 224 | isa = XCConfigurationList; 225 | buildConfigurations = ( 226 | 5529515318AEF6EF0086301E /* Debug */, 227 | 5529515418AEF6EF0086301E /* Release */, 228 | ); 229 | defaultConfigurationIsVisible = 0; 230 | defaultConfigurationName = Release; 231 | }; 232 | /* End XCConfigurationList section */ 233 | }; 234 | rootObject = 5529514118AEF6EF0086301E /* Project object */; 235 | } 236 | -------------------------------------------------------------------------------- /get_aslr.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /get_aslr/Attach.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Attach.mm 3 | * MachOView 4 | * 5 | * Created by fG! on 08/09/13. 6 | * reverser@put.as 7 | * 8 | * Contains functions for the attach to process feature. 9 | * 10 | */ 11 | 12 | #include "Attach.h" 13 | 14 | #include 15 | #include 16 | 17 | /* local functions */ 18 | static kern_return_t readmem(mach_vm_offset_t *buffer, mach_vm_address_t address, mach_vm_size_t size, pid_t pid, vm_region_basic_info_data_64_t *info); 19 | 20 | #pragma mark Public functions 21 | 22 | /* 23 | * find main binary by iterating memory region 24 | * assumes there's only one binary with filetype == MH_EXECUTE 25 | */ 26 | kern_return_t 27 | find_main_binary(pid_t pid, mach_vm_address_t *main_address) 28 | { 29 | vm_map_t targetTask = 0; 30 | kern_return_t kr = 0; 31 | if (task_for_pid(mach_task_self(), pid, &targetTask)) 32 | { 33 | return KERN_FAILURE; 34 | } 35 | 36 | vm_address_t iter = 0; 37 | while (1) 38 | { 39 | struct mach_header mh = {0}; 40 | vm_address_t addr = iter; 41 | vm_size_t lsize = 0; 42 | uint32_t depth; 43 | mach_vm_size_t bytes_read = 0; 44 | struct vm_region_submap_info_64 info; 45 | mach_msg_type_number_t count = VM_REGION_SUBMAP_INFO_COUNT_64; 46 | if (vm_region_recurse_64(targetTask, &addr, &lsize, &depth, (vm_region_info_t)&info, &count)) 47 | { 48 | break; 49 | } 50 | kr = mach_vm_read_overwrite(targetTask, (mach_vm_address_t)addr, (mach_vm_size_t)sizeof(struct mach_header), (mach_vm_address_t)&mh, &bytes_read); 51 | if (kr == KERN_SUCCESS && bytes_read == sizeof(struct mach_header)) 52 | { 53 | /* only one image with MH_EXECUTE filetype */ 54 | if ( (mh.magic == MH_MAGIC || mh.magic == MH_MAGIC_64) && mh.filetype == MH_EXECUTE) 55 | { 56 | *main_address = addr; 57 | break; 58 | } 59 | } 60 | iter = addr + lsize; 61 | } 62 | return KERN_SUCCESS; 63 | } 64 | 65 | /* 66 | * we need to find the binary file size 67 | * which is taken from the filesize field of each segment command 68 | * and not the vmsize (because of alignment) 69 | * if we dump using vmaddresses, we will get the alignment space into the dumped 70 | * binary and get into problems :-) 71 | */ 72 | int64_t 73 | get_image_size(mach_vm_address_t address, pid_t pid, uint64_t *vmaddr_slide) 74 | { 75 | vm_region_basic_info_data_64_t region_info = {0}; 76 | // allocate a buffer to read the header info 77 | // NOTE: this is not exactly correct since the 64bit version has an extra 4 bytes 78 | // but this will work for this purpose so no need for more complexity! 79 | struct mach_header header = {0}; 80 | if (readmem((mach_vm_offset_t*)&header, address, sizeof(struct mach_header), pid, ®ion_info)) 81 | { 82 | return -1; 83 | } 84 | 85 | if (header.magic != MH_MAGIC && header.magic != MH_MAGIC_64) 86 | { 87 | printf("[ERROR] Target is not a mach-o binary!\n"); 88 | return -1; 89 | } 90 | 91 | int64_t imagefilesize = -1; 92 | /* read the load commands */ 93 | uint8_t *loadcmds = (uint8_t*)malloc(header.sizeofcmds); 94 | uint16_t mach_header_size = sizeof(struct mach_header); 95 | if (header.magic == MH_MAGIC_64) 96 | { 97 | mach_header_size = sizeof(struct mach_header_64); 98 | } 99 | if (readmem((mach_vm_offset_t*)loadcmds, address+mach_header_size, header.sizeofcmds, pid, ®ion_info)) 100 | { 101 | return -1; 102 | } 103 | 104 | /* process and retrieve address and size of linkedit */ 105 | uint8_t *loadCmdAddress = 0; 106 | loadCmdAddress = (uint8_t*)loadcmds; 107 | struct load_command *loadCommand = NULL; 108 | struct segment_command *segCmd = NULL; 109 | struct segment_command_64 *segCmd64 = NULL; 110 | for (uint32_t i = 0; i < header.ncmds; i++) 111 | { 112 | loadCommand = (struct load_command*)loadCmdAddress; 113 | if (loadCommand->cmd == LC_SEGMENT) 114 | { 115 | segCmd = (struct segment_command*)loadCmdAddress; 116 | if (strncmp(segCmd->segname, "__PAGEZERO", 16) != 0) 117 | { 118 | if (strncmp(segCmd->segname, "__TEXT", 16) == 0) 119 | { 120 | *vmaddr_slide = address - segCmd->vmaddr; 121 | } 122 | imagefilesize += segCmd->filesize; 123 | } 124 | } 125 | else if (loadCommand->cmd == LC_SEGMENT_64) 126 | { 127 | segCmd64 = (struct segment_command_64*)loadCmdAddress; 128 | if (strncmp(segCmd64->segname, "__PAGEZERO", 16) != 0) 129 | { 130 | if (strncmp(segCmd64->segname, "__TEXT", 16) == 0) 131 | { 132 | *vmaddr_slide = address - segCmd64->vmaddr; 133 | } 134 | imagefilesize += segCmd64->filesize; 135 | } 136 | } 137 | // advance to next command 138 | loadCmdAddress += loadCommand->cmdsize; 139 | } 140 | free(loadcmds); 141 | return imagefilesize; 142 | } 143 | 144 | /* 145 | * dump the binary into the allocated buffer 146 | * we dump each segment and advance the buffer 147 | */ 148 | kern_return_t 149 | dump_binary(mach_vm_address_t address, pid_t pid, uint8_t *buffer, uint64_t aslr_slide) 150 | { 151 | vm_region_basic_info_data_64_t region_info = {0}; 152 | // allocate a buffer to read the header info 153 | // NOTE: this is not exactly correct since the 64bit version has an extra 4 bytes 154 | // but this will work for this purpose so no need for more complexity! 155 | struct mach_header header = {0}; 156 | if (readmem((mach_vm_offset_t*)&header, address, sizeof(struct mach_header), pid, ®ion_info)) 157 | { 158 | return KERN_FAILURE; 159 | } 160 | 161 | if (header.magic != MH_MAGIC && header.magic != MH_MAGIC_64) 162 | { 163 | printf("[ERROR] Target is not a mach-o binary!\n"); 164 | return KERN_FAILURE; 165 | } 166 | 167 | // read the header info to find the LINKEDIT 168 | uint8_t *loadcmds = (uint8_t*)malloc(header.sizeofcmds); 169 | 170 | uint16_t mach_header_size = sizeof(struct mach_header); 171 | if (header.magic == MH_MAGIC_64) 172 | { 173 | mach_header_size = sizeof(struct mach_header_64); 174 | } 175 | // retrieve the load commands 176 | if (readmem((mach_vm_offset_t*)loadcmds, address+mach_header_size, header.sizeofcmds, pid, ®ion_info)) 177 | { 178 | return KERN_FAILURE; 179 | } 180 | 181 | // process and retrieve address and size of linkedit 182 | uint8_t *loadCmdAddress = 0; 183 | loadCmdAddress = (uint8_t*)loadcmds; 184 | struct load_command *loadCommand = NULL; 185 | struct segment_command *segCmd = NULL; 186 | struct segment_command_64 *segCmd64 = NULL; 187 | for (uint32_t i = 0; i < header.ncmds; i++) 188 | { 189 | loadCommand = (struct load_command*)loadCmdAddress; 190 | if (loadCommand->cmd == LC_SEGMENT) 191 | { 192 | segCmd = (struct segment_command*)loadCmdAddress; 193 | if (strncmp(segCmd->segname, "__PAGEZERO", 16) != 0) 194 | { 195 | readmem((mach_vm_offset_t*)buffer, segCmd->vmaddr+aslr_slide, segCmd->filesize, pid, ®ion_info); 196 | } 197 | buffer += segCmd->filesize; 198 | } 199 | else if (loadCommand->cmd == LC_SEGMENT_64) 200 | { 201 | segCmd64 = (struct segment_command_64*)loadCmdAddress; 202 | if (strncmp(segCmd64->segname, "__PAGEZERO", 16) != 0) 203 | { 204 | readmem((mach_vm_offset_t*)buffer, segCmd64->vmaddr+aslr_slide, segCmd64->filesize, pid, ®ion_info); 205 | } 206 | buffer += segCmd64->filesize; 207 | } 208 | // advance to next command 209 | loadCmdAddress += loadCommand->cmdsize; 210 | } 211 | free(loadcmds); 212 | return KERN_SUCCESS; 213 | } 214 | 215 | #pragma mark Local functions 216 | 217 | static kern_return_t 218 | readmem(mach_vm_offset_t *buffer, mach_vm_address_t address, mach_vm_size_t size, pid_t pid, vm_region_basic_info_data_64_t *info) 219 | { 220 | // get task for pid 221 | vm_map_t port; 222 | 223 | kern_return_t kr; 224 | //#if DEBUG 225 | // printf("[DEBUG] Readmem of address %llx to buffer %llx with size %llx\n", address, buffer, size); 226 | //#endif 227 | if (task_for_pid(mach_task_self(), pid, &port)) 228 | { 229 | fprintf(stderr, "[ERROR] Can't execute task_for_pid! Do you have the right permissions/entitlements?\n"); 230 | return KERN_FAILURE; 231 | } 232 | 233 | mach_msg_type_number_t info_cnt = sizeof (vm_region_basic_info_data_64_t); 234 | mach_port_t object_name; 235 | mach_vm_size_t size_info; 236 | mach_vm_address_t address_info = address; 237 | kr = mach_vm_region(port, &address_info, &size_info, VM_REGION_BASIC_INFO_64, (vm_region_info_t)info, &info_cnt, &object_name); 238 | if (kr) 239 | { 240 | fprintf(stderr, "[ERROR] mach_vm_region failed with error %d\n", (int)kr); 241 | return KERN_FAILURE; 242 | } 243 | 244 | /* read memory - vm_read_overwrite because we supply the buffer */ 245 | mach_vm_size_t nread; 246 | kr = mach_vm_read_overwrite(port, address, size, (mach_vm_address_t)buffer, &nread); 247 | if (kr) 248 | { 249 | fprintf(stderr, "[ERROR] vm_read failed! %d\n", kr); 250 | return KERN_FAILURE; 251 | } 252 | else if (nread != size) 253 | { 254 | fprintf(stderr, "[ERROR] vm_read failed! requested size: 0x%llx read: 0x%llx\n", size, nread); 255 | return KERN_FAILURE; 256 | } 257 | return KERN_SUCCESS; 258 | } 259 | -------------------------------------------------------------------------------- /get_aslr/Attach.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Attach.h 3 | * MachOView 4 | * 5 | * Created by fG! on 08/09/13. 6 | * reverser@put.as 7 | * 8 | */ 9 | 10 | #ifndef get_aslr_Attach_h 11 | #define get_aslr_Attach_h 12 | 13 | #include 14 | #include 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | int64_t get_image_size(mach_vm_address_t address, pid_t pid, uint64_t *vmaddr_slide); 22 | kern_return_t find_main_binary(pid_t pid, mach_vm_address_t *main_address); 23 | kern_return_t dump_binary(mach_vm_address_t address, pid_t pid, uint8_t *buffer, uint64_t aslr_slide); 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /get_aslr/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "Attach.h" 4 | 5 | int main(int argc, const char * argv[]) { 6 | if(argc != 2) { 7 | printf("Usage: get_aslr pid\n"); 8 | return 1; 9 | } 10 | 11 | if(getuid() != 0) { 12 | printf("If you see any errors, you should probably run this as root.\n"); 13 | } 14 | 15 | pid_t pid = (pid_t)strtol(argv[1], NULL, 0); 16 | 17 | mach_vm_address_t main_address; 18 | if(find_main_binary(pid, &main_address) != KERN_SUCCESS) { 19 | printf("Failed to find address of header!\n"); 20 | return 1; 21 | } 22 | 23 | uint64_t aslr_slide; 24 | if(get_image_size(main_address, pid, &aslr_slide) == -1) { 25 | printf("Failed to find ASLR slide!\n"); 26 | return 1; 27 | } 28 | 29 | printf("ASLR slide: 0x%llx\n", aslr_slide); 30 | 31 | return 0; 32 | } 33 | 34 | --------------------------------------------------------------------------------