1. 说明

Android 7.0 后使用 dlopen 函数无法获取 soinfo 对应,因此也无法使用 dlsym 函数去调用第三方的 so 内的函数。这里给出 dlopen() 函数的源码分析。

不同点可参考:https://blog.csdn.net/u011247544/article/details/75262360

2. 源码分析

1. dlopen 函数

函数调用会首先走到 dlfcn.cpp 类内的 dlopen 函数(/bionic/linker/dlfcn.cpp)

85void* dlopen(const char* filename, int flags) {

86 void* caller_addr = __builtin_return_address(0);

87 return dlopen_ext(filename, flags, nullptr, caller_addr);

88}

69static void* dlopen_ext(const char* filename, int flags,

70 const android_dlextinfo* extinfo, void* caller_addr) {

71 ScopedPthreadMutexLocker locker(&g_dl_mutex);

72 void* result = do_dlopen(filename, flags, extinfo, caller_addr); // 调到 linker.cpp 类内

73 if (result == nullptr) {

74 __bionic_format_dlerror("dlopen failed", linker_get_error_buffer());

75 return nullptr;

76 }

77 return result;

78}

2. do_dlopen() 函数

这个函数实现在 linker.cpp 类内。do_dlopen 函数会调用 find_library 函数返回 soinfo 对象,并最终调用 si->to_handle() 函数返回 handle_。(/bionic/linker/linker.cpp)

2333void* do_dlopen(const char* name, int flags, const android_dlextinfo* extinfo,

2334 void* caller_addr) {

2335 soinfo* const caller = find_containing_library(caller_addr);

2336

2337 if ((flags & ~(RTLD_NOW|RTLD_LAZY|RTLD_LOCAL|RTLD_GLOBAL|RTLD_NODELETE|RTLD_NOLOAD)) != 0) {

2338 DL_ERR("invalid flags to dlopen: %x", flags);

2339 return nullptr;

2340 }

2341

2342 android_namespace_t* ns = get_caller_namespace(caller);

2343

2344 if (extinfo != nullptr) {

2345 if ((extinfo->flags & ~(ANDROID_DLEXT_VALID_FLAG_BITS)) != 0) {

2346 DL_ERR("invalid extended flags to android_dlopen_ext: 0x%" PRIx64, extinfo->flags);

2347 return nullptr;

2348 }

2349

2350 if ((extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_FD) == 0 &&

2351 (extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET) != 0) {

2352 DL_ERR("invalid extended flag combination (ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET without "

2353 "ANDROID_DLEXT_USE_LIBRARY_FD): 0x%" PRIx64, extinfo->flags);

2354 return nullptr;

2355 }

2356

2357 if ((extinfo->flags & ANDROID_DLEXT_LOAD_AT_FIXED_ADDRESS) != 0 &&

2358 (extinfo->flags & (ANDROID_DLEXT_RESERVED_ADDRESS | ANDROID_DLEXT_RESERVED_ADDRESS_HINT)) != 0) {

2359 DL_ERR("invalid extended flag combination: ANDROID_DLEXT_LOAD_AT_FIXED_ADDRESS is not "

2360 "compatible with ANDROID_DLEXT_RESERVED_ADDRESS/ANDROID_DLEXT_RESERVED_ADDRESS_HINT");

2361 return nullptr;

2362 }

2363

2364 if ((extinfo->flags & ANDROID_DLEXT_USE_NAMESPACE) != 0) {

2365 if (extinfo->library_namespace == nullptr) {

2366 DL_ERR("ANDROID_DLEXT_USE_NAMESPACE is set but extinfo->library_namespace is null");

2367 return nullptr;

2368 }

2369 ns = extinfo->library_namespace;

2370 }

2371 }

2372

2373 ProtectedDataGuard guard;

2374 soinfo* si = find_library(ns, name, flags, extinfo, caller); // 这里往下调用返回 soinfo 对象

2375 if (si != nullptr) {

2376 si->call_constructors();

2377 return si->to_handle(); // 这里返回的是 调用 to_handle() 函数

2378 }

2379

2380 return nullptr;

2381}

下面给处 find_library 函数的追踪:

首先是 find_library 函数

2159static soinfo* find_library(android_namespace_t* ns,

2160 const char* name, int rtld_flags,

2161 const android_dlextinfo* extinfo,

2162 soinfo* needed_by) {

2163 soinfo* si;

2164

2165 if (name == nullptr) {

2166 si = somain;

2167 } else if (!find_libraries(ns, needed_by, &name, 1, &si, nullptr, 0, rtld_flags,

2168 extinfo, /* add_as_children */ false)) {

2169 return nullptr;

2170 }

2171

2172 return si;

2173}

接着是 find_libraries 函数,源码分析知道这个函数分为 4 步,暂未做具体分析

1994static bool find_libraries(android_namespace_t* ns,

1995 soinfo* start_with,

1996 const char* const library_names[],

1997 size_t library_names_count, soinfo* soinfos[],

1998 std::vector* ld_preloads,

1999 size_t ld_preloads_count, int rtld_flags,

2000 const android_dlextinfo* extinfo,

2001 bool add_as_children) {

2002 // Step 0: prepare.

2003 LoadTaskList load_tasks;

2004 std::unordered_mapreaders_map;

...

2053 if(!find_library_internal(ns, task, &zip_archive_cache, &load_tasks, rtld_flags)) {

2054 return false;

2055 }

...

2156 return linked;

2157}

然后是 find_library_internal 函数

1896static bool find_library_internal(android_namespace_t* ns,

1897 LoadTask* task,

1898 ZipArchiveCache* zip_archive_cache,

1899 LoadTaskList* load_tasks,

1900 int rtld_flags) {

1901 soinfo* candidate;

1902

1903 if (find_loaded_library_by_soname(ns, task->get_name(), &candidate)) {

1904 task->set_soinfo(candidate);

1905 return true;

1906 }

1907

1908 if (ns != &g_default_namespace) {

1909 // check public namespace

1910 candidate = g_public_namespace.find_if([&](soinfo* si) {

1911 return strcmp(task->get_name(), si->get_soname()) == 0;

1912 });

1913

1914 if (candidate != nullptr) {

1915 ns->add_soinfo(candidate);

1916 task->set_soinfo(candidate);

1917 return true;

1918 }

1919 }

1920

1921 // Library might still be loaded, the accurate detection

1922 // of this fact is done by load_library.

1923 TRACE("[ \"%s\" find_loaded_library_by_soname failed (*candidate=%s@%p). Trying harder...]",

1924 task->get_name(), candidate == nullptr ? "n/a" : candidate->get_realpath(), candidate);

1925

1926 if (load_library(ns, task, zip_archive_cache, load_tasks, rtld_flags)) {

1927 return true;

1928 } else {

1929 // In case we were unable to load the library but there

1930 // is a candidate loaded under the same soname but different

1931 // sdk level - return it anyways.

1932 if (candidate != nullptr) {

1933 task->set_soinfo(candidate);

1934 return true;

1935 }

1936 }

1937

1938 return false;

1939}

3. soinfo::to_handle() 函数

(/bionic/linker/linker.cpp)

do_dlopen 函数的最终返回是这个函数的返回,看下 这个函数的实现:

3442void* soinfo::to_handle() {

3443 if (get_application_target_sdk_version() <= 23 || !has_min_version(3)) {

3444 return this;

3445 }

3446

3447 return reinterpret_cast(get_handle());

3448}

然后调用了 get_handle() 函数。这个函数就是返回了 handle_

3436uintptr_t soinfo::get_handle() const {

3437 CHECK(has_min_version(3));

3438 CHECK(handle_ != 0);

3439 return handle_;

3440}

那 handle_ 的生成是在哪里呢?是在同目录下的 generate_handle 函数

3450void soinfo::generate_handle() {

3451 CHECK(has_min_version(3));

3452 CHECK(handle_ == 0); // Make sure this is the first call

3453

3454 // Make sure the handle is unique and does not collide

3455 // with special values which are RTLD_DEFAULT and RTLD_NEXT.

3456 do {

3457 arc4random_buf(&handle_, sizeof(handle_));

3458 // the least significant bit for the handle is always 1

3459 // making it easy to test the type of handle passed to

3460 // dl* functions.

3461 handle_ = handle_ | 1;

3462 } while (handle_ == reinterpret_cast(RTLD_DEFAULT) ||

3463 handle_ == reinterpret_cast(RTLD_NEXT) ||

3464 g_soinfo_handles_map.find(handle_) != g_soinfo_handles_map.end());

3465

3466 g_soinfo_handles_map[handle_] = this;

3467}

由上可以看出, handle_ 是 arc4random_buf(&handle_, sizeof(handle_)); 函数生成的随机值。并将这个值放到 static std::unordered_mapg_soinfo_handles_map 内,这个值与 soinfo 对应。

4. soinfo 结构体

soinfo 结构体就是 so 文件解析后的数据信息,解析处的 节信息,等等等等~~

176struct soinfo {

177 public:

178 typedef LinkedListsoinfo_list_t;

179 typedef LinkedListandroid_namespace_list_t;

180#if defined(__work_around_b_24465209__)

181 private:

182 char old_name_[SOINFO_NAME_LEN];

183#endif

184 public:

185 const ElfW(Phdr)* phdr;

186 size_t phnum;

187 ElfW(Addr) entry;

188 ElfW(Addr) base;

189 size_t size;

190

191#if defined(__work_around_b_24465209__)

192 uint32_t unused1; // DO NOT USE, maintained for compatibility.

193#endif

194

195 ElfW(Dyn)* dynamic;

196

197#if defined(__work_around_b_24465209__)

198 uint32_t unused2; // DO NOT USE, maintained for compatibility

199 uint32_t unused3; // DO NOT USE, maintained for compatibility

200#endif

201

202 soinfo* next;

203 private:

204 uint32_t flags_;

205

206 const char* strtab_;

207 ElfW(Sym)* symtab_;

208

209 size_t nbucket_;

210 size_t nchain_;

211 uint32_t* bucket_;

212 uint32_t* chain_;

213

214#if defined(__mips__) || !defined(__LP64__)

215 // This is only used by mips and mips64, but needs to be here for

216 // all 32-bit architectures to preserve binary compatibility.

217 ElfW(Addr)** plt_got_;

218#endif

219

220#if defined(USE_RELA)

221 ElfW(Rela)* plt_rela_;

222 size_t plt_rela_count_;

223

224 ElfW(Rela)* rela_;

225 size_t rela_count_;

226#else

227 ElfW(Rel)* plt_rel_;

228 size_t plt_rel_count_;

229

230 ElfW(Rel)* rel_;

231 size_t rel_count_;

232#endif

233

234 linker_function_t* preinit_array_;

235 size_t preinit_array_count_;

236

237 linker_function_t* init_array_;

238 size_t init_array_count_;

239 linker_function_t* fini_array_;

240 size_t fini_array_count_;

241

242 linker_function_t init_func_;

243 linker_function_t fini_func_;

244

245#if defined(__arm__)

246 public:

247 // ARM EABI section used for stack unwinding.

248 uint32_t* ARM_exidx;

249 size_t ARM_exidx_count;

250 private:

251#elif defined(__mips__)

252 uint32_t mips_symtabno_;

253 uint32_t mips_local_gotno_;

254 uint32_t mips_gotsym_;

255 bool mips_relocate_got(const VersionTracker& version_tracker,

256 const soinfo_list_t& global_group,

257 const soinfo_list_t& local_group);

258#if !defined(__LP64__)

259 bool mips_check_and_adjust_fp_modes();

260#endif

261#endif

262 size_t ref_count_;

263 public:

264 link_map link_map_head;

265

266 bool constructors_called;

267

268 // When you read a virtual address from the ELF file, add this

269 // value to get the corresponding address in the process' address space.

270 ElfW(Addr) load_bias;

271

272#if !defined(__LP64__)

273 bool has_text_relocations;

274#endif

275 bool has_DT_SYMBOLIC;

276

277 public:

278 soinfo(android_namespace_t* ns, const char* name, const struct stat* file_stat,

279 off64_t file_offset, int rtld_flags);

280 ~soinfo();

281

282 void call_constructors();

283 void call_destructors();

284 void call_pre_init_constructors();

285 bool prelink_image();

286 bool link_image(const soinfo_list_t& global_group, const soinfo_list_t& local_group,

287 const android_dlextinfo* extinfo);

288 bool protect_relro();

289

290 void add_child(soinfo* child);

291 void remove_all_links();

292

293 ino_t get_st_ino() const;

294 dev_t get_st_dev() const;

295 off64_t get_file_offset() const;

296

297 uint32_t get_rtld_flags() const;

298 uint32_t get_dt_flags_1() const;

299 void set_dt_flags_1(uint32_t dt_flags_1);

300

301 soinfo_list_t& get_children();

302 const soinfo_list_t& get_children() const;

303

304 soinfo_list_t& get_parents();

305

306 bool find_symbol_by_name(SymbolName& symbol_name,

307 const version_info* vi,

308 const ElfW(Sym)** symbol) const;

309

310 ElfW(Sym)* find_symbol_by_address(const void* addr);

311 ElfW(Addr) resolve_symbol_address(const ElfW(Sym)* s) const;

312

313 const char* get_string(ElfW(Word) index) const;

314 bool can_unload() const;

315 bool is_gnu_hash() const;

316

317 bool inline has_min_version(uint32_t min_version __unused) const {

318#if defined(__work_around_b_24465209__)

319 return (flags_ & FLAG_NEW_SOINFO) != 0 && version_ >= min_version;

320#else

321 return true;

322#endif

323 }

325 bool is_linked() const;

326 bool is_linker() const;

327 bool is_main_executable() const;

328

329 void set_linked();

330 void set_linker_flag();

331 void set_main_executable();

332 void set_nodelete();

333

334 void increment_ref_count();

335 size_t decrement_ref_count();

336

337 soinfo* get_local_group_root() const;

338

339 void set_soname(const char* soname);

340 const char* get_soname() const;

341 const char* get_realpath() const;

342 const ElfW(Versym)* get_versym(size_t n) const;

343 ElfW(Addr) get_verneed_ptr() const;

344 size_t get_verneed_cnt() const;

345 ElfW(Addr) get_verdef_ptr() const;

346 size_t get_verdef_cnt() const;

347

348 bool find_verdef_version_index(const version_info* vi, ElfW(Versym)* versym) const;

349

350 uint32_t get_target_sdk_version() const;

351

352 void set_dt_runpath(const char *);

353 const std::vector& get_dt_runpath() const;

354 android_namespace_t* get_primary_namespace();

355 void add_secondary_namespace(android_namespace_t* secondary_ns);

356

357 void set_mapped_by_caller(bool reserved_map);

358 bool is_mapped_by_caller() const;

359

360 uintptr_t get_handle() const;

361 void generate_handle();

362 void* to_handle();

363

364 private:

365 bool elf_lookup(SymbolName& symbol_name, const version_info* vi, uint32_t* symbol_index) const;

366 ElfW(Sym)* elf_addr_lookup(const void* addr);

367 bool gnu_lookup(SymbolName& symbol_name, const version_info* vi, uint32_t* symbol_index) const;

368 ElfW(Sym)* gnu_addr_lookup(const void* addr);

369

370 bool lookup_version_info(const VersionTracker& version_tracker, ElfW(Word) sym,

371 const char* sym_name, const version_info** vi);

372

373 void call_array(const char* array_name, linker_function_t* functions, size_t count, bool reverse);

374 void call_function(const char* function_name, linker_function_t function);

375 template376 bool relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& rel_iterator,

377 const soinfo_list_t& global_group, const soinfo_list_t& local_group);

378

379 private:

380 // This part of the structure is only available

381 // when FLAG_NEW_SOINFO is set in this->flags.

382 uint32_t version_;

383

384 // version >= 0

385 dev_t st_dev_;

386 ino_t st_ino_;

387

388 // dependency graph

389 soinfo_list_t children_;

390 soinfo_list_t parents_;

391

392 // version >= 1

393 off64_t file_offset_;

394 uint32_t rtld_flags_;

395 uint32_t dt_flags_1_;

396 size_t strtab_size_;

397

398 // version >= 2

399

400 size_t gnu_nbucket_;

401 uint32_t* gnu_bucket_;

402 uint32_t* gnu_chain_;

403 uint32_t gnu_maskwords_;

404 uint32_t gnu_shift2_;

405 ElfW(Addr)* gnu_bloom_filter_;

406

407 soinfo* local_group_root_;

408

409 uint8_t* android_relocs_;

410 size_t android_relocs_size_;

411

412 const char* soname_;

413 std::string realpath_;

414

415 const ElfW(Versym)* versym_;

416

417 ElfW(Addr) verdef_ptr_;

418 size_t verdef_cnt_;

419

420 ElfW(Addr) verneed_ptr_;

421 size_t verneed_cnt_;

422

423 uint32_t target_sdk_version_;

424

425 // version >= 3

426 std::vectordt_runpath_;

427 android_namespace_t* primary_namespace_;

428 android_namespace_list_t secondary_namespaces_;

429 uintptr_t handle_;

430

431 friend soinfo* get_libdl_info();

432};

android 禁用dlsym_Android 7.0 dlopen 函数分析相关推荐

  1. android7dlopen,Android 7.0 dlopen 函数分析

    1. 说明 Android 7.0 后使用 dlopen 函数无法获取 soinfo 对应,因此也无法使用 dlsym 函数去调用第三方的 so 内的函数.这里给出 dlopen() 函数的源码分析. ...

  2. 关于dlopen函数分析

    为什么80%的码农都做不了架构师?>>>    dlopen 函数原型: void*        dlopen(const char*  filename, int flag); ...

  3. android游戏开发笔记(0)——游戏开发分析及开发所需知识

    琴弦jerry 原创文章  转载请遵循 "署名-非商用-禁止演绎 2.5 中国大陆"创作共用协议 转载请保留原文链接:http://www.jerry-zhang.com/inde ...

  4. 【Android 逆向】Android 进程注入工具开发 ( 注入代码分析 | 获取 linker 中的 dlopen 函数地址 并 通过 远程调用 执行该函数 )

    文章目录 一.dlopen 函数简介 二.获取 目标进程 linker 中的 dlopen 函数地址 三.远程调用 目标进程 linker 中的 dlopen 函数 一.dlopen 函数简介 dlo ...

  5. 【Android 逆向】Android 进程注入工具开发 ( 注入代码分析 | 获取注入的 libbridge.so 动态库中的 load 函数地址 并 通过 远程调用 执行该函数 )

    文章目录 一.dlsym 函数简介 二.获取 目标进程 linker 中的 dlsym 函数地址 三.远程调用 目标进程 linker 中的 dlsym 函数 获取 注入的 libbridge.so ...

  6. 【Android 逆向】Android 进程注入工具开发 ( 注入代码分析 | 远程调用 目标进程中 libc.so 动态库中的 mmap 函数 三 | 等待远程函数执行完毕 | 寄存器获取返回值 )

    文章目录 前言 一.等待远程进程 mmap 函数执行完毕 二.从寄存器中获取进程返回值 三.博客资源 前言 前置博客 : [Android 逆向]Android 进程注入工具开发 ( 注入代码分析 | ...

  7. 【Android 逆向】Android 进程注入工具开发 ( 注入代码分析 | 远程调用 目标进程中 libc.so 动态库中的 mmap 函数 二 | 准备参数 | 远程调用 mmap 函数 )

    文章目录 一.准备 mmap 函数的参数 二.mmap 函数远程调用 一.准备 mmap 函数的参数 上一篇博客 [Android 逆向]Android 进程注入工具开发 ( 注入代码分析 | 远程调 ...

  8. Android 6.0 JNI原理分析 和 Linux系统调用(syscall)原理

    JNI原理 引言:分析Android源码6.0的过程,一定离不开Java与C/C++代码直接的来回跳转,那么就很有必要掌握JNI,这是链接Java层和Native层的桥梁,本文涉及相关源码: fram ...

  9. 【Android 逆向】Dalvik 函数抽取加壳 ( 类加载流程分析 | Class.cpp#findClassNoInit 函数 | DexFile.cpp#dexFindClass 函数分析 )

    文章目录 前言 一.Class.cpp#dvmDefineClass 函数分析 二.Class.cpp#findClassNoInit 函数分析 三.DexFile.cpp#dexFindClass ...

最新文章

  1. 【Java Web开发指南】Mybatis一对多关联映射
  2. Python黑科技,教你学会Django系统错误监控
  3. visual studio 2019安装配置可编写c/c++语言的IDE环境
  4. 坚持不放弃,修得好结果。
  5. 分析称地图服务将成移动行业未来
  6. UI设计素材|卡券界面设计
  7. 惊恐的市场洗牌网游市场诞生危机论
  8. 正常使用 flex profiler 解决 Socket timeout
  9. 常见的电子商务模式理解
  10. [saiku] JCR在saiku中的运用原理
  11. 2020年度SaaS企业 TOP100
  12. vue2项目中全局引入scss变量
  13. Polar Si9000如何选择模型计算射频线宽?
  14. QListView当前页(可视范围)全选反选
  15. 不透明度百分比 16进制值对照表;rgb色值16进制转化原理
  16. rar文件ubuntu_如何在Ubuntu上提取RAR文件
  17. java多线程简单模拟12306抢票
  18. VCL组件DevExpress VCL v21.2 - 甘特图、网格控件升级
  19. Web前端-网站首页和注册界面的实现
  20. ubuntu查服务器型号,查看Ubuntu服务器的版本信息

热门文章

  1. 用SQL进行用户留存率计算
  2. SAP Spartacus 中的 Commands and queries
  3. SAP 电商云 Spartacus UI 产品搜索结果的设计明细
  4. 什么是 SAP Spartacus UI 的 direction 服务
  5. SAP Spartacus 电商云 UI Shipping Method 在单元测试环境下没有显示的问题
  6. 一个详尽的面向 SAP UI5 初学者的教程 - 如何在 SAP UI5 中绘制图表 Chart
  7. 想调试Angular框架的@HostBinding,应该在哪里设置断点
  8. scratch desktop的基本使用 - 如何使用积木
  9. 在Google Cloud platform上创建Kubernetes cluster并使用
  10. 使用Fiddler为满足某些特定格式的网络请求返回mock响应