GKLBB

当你经历了暴风雨,你也就成为了暴风雨

导航

应用安全 --- 逆向技巧 之 ida如何区分哪些是自定义函数,哪些是系统函数

函数分类分析

一、自定义函数(用户编写的业务逻辑)

1. JNI 导出函数(最核心)

text
Java_com_example_helloworld_MainActivity_stringFromJNI
地址: 0x1ED00
特征: Java_包名_类名_方法名 格式,这是唯一的JNI导出函数
这是整个so库对外暴露的唯一接口

2. 未命名的内部函数(sub_xxxx)

text
# 与JNI函数直接相关的核心函数
sub_1EE5C   0x1EE5C   大小:0x24   ← 被JNI函数直接调用,最可疑的核心逻辑
sub_1ECB0   0x1ECB0   大小:0x10
sub_1ECC0   0x1ECC0   大小:0x08
sub_1ECC8   0x1ECC8   大小:0x08
sub_1ECD0   0x1ECD0   大小:0x14
sub_1ECE4   0x1ECE4   大小:0x1C

# 与JNI函数地址相近的辅助函数
sub_1EEF8   0x1EEF8
sub_1EF0C   0x1EF0C
sub_1EF20   0x1EF20
sub_1EF48   0x1EF48
sub_1EF58   0x1EF58
sub_1EF80   0x1EF80
sub_1EF94   0x1EF94
sub_1EFE8   0x1EFE8
sub_1F01C   0x1F01C
sub_1F044   0x1F044
sub_1F070   0x1F070

二、系统/外部函数分类

1. C 标准库函数(libc.so)

text
# 内存操作
malloc          0x049F00
free            0x049F08
realloc         0x04A068
memcpy          0x049F28
memmove         0x049F20
memset          0x049F38
memchr          0x049F30
memcmp          0x049F40
posix_memalign  0x04A010

# 字符串操作
strlen          0x049F18
strcmp          0x04A090
strncmp         0x04A0D0
snprintf        0x049FE0
fprintf         0x04A0D8
fwrite          0x04A108
fflush          0x04A0E0
fputc           0x04A030

# 数值转换
strtol          0x049FF0
strtoul         0x049F80
strtoll         0x049F90
strtoull        0x049FA0
strtod          0x049FC0
strtof          0x049FB0
strtold         0x049FD0

# 宽字符操作
wcslen          0x049F58
wmemcpy         0x049F50
wmemmove        0x049F48
wmemset         0x049F68
wmemchr         0x049F60
wmemcmp         0x049F70
wcstol          0x049FF8
wcstoul         0x049F88
wcstod          0x049FC8

# 其他系统函数
abort           0x04A060
__stack_chk_fail    0x049F10   ← 栈保护
__errno             0x049F78
__strlen_chk        0x04A018
__memmove_chk       0x04A070
__vsnprintf_chk     0x04A078

2. C++ 标准库函数(libc++.so / libstdc++)

text
# 内存管理
operator new(ulong)                     0x026EC0
operator new[](ulong)                   0x026F5C
operator delete(void*)                  0x026F94
operator delete[](void*)                0x026FAC

# std::string 操作(大量内联到.text段)
std::string::basic_string(char const*)  0x1EDAC  ← 构造函数
std::string::~string()                  0x1F840  ← 析构函数
std::string::__init(char const*,ulong)  0x1FB38
std::string::append(char const*)        0x021000
std::string::assign(char const*)        0x020CA0
std::string::find(...)                  0x020D6C
std::string::compare(...)               0x020A78
std::string::reserve(ulong)             0x01FF98

# std::wstring 操作
std::wstring::__init(...)               0x021D04
std::wstring::append(...)               0x023070
std::wstring::assign(...)               0x022D88

# 数值转换
std::to_string(int)                     0x024F64
std::to_string(long)                    0x025060
std::to_string(double)                  0x025FFC
std::to_wstring(int)                    0x0255A0

# 异常相关
std::__throw_bad_alloc()               0x026E88
std::bad_alloc::bad_alloc()            0x03ED18
std::logic_error::logic_error()        0x027118
std::runtime_error::runtime_error()    0x027368
std::terminate()                        0x028218
std::unexpected()                       0x0281FC

3. C++ ABI 异常处理函数(libgcc / unwind)

text
__cxa_throw                  0x027A58   ← 抛出异常
__cxa_begin_catch            0x027B8C   ← 捕获异常开始
__cxa_end_catch              0x027C2C   ← 捕获异常结束
__cxa_rethrow                0x027DBC   ← 重新抛出
__cxa_allocate_exception     0x02799C   ← 分配异常对象
__cxa_free_exception         0x0279F0   ← 释放异常对象
__cxa_call_unexpected        0x03CD88   ← 意外异常处理
__cxa_demangle               0x028548   ← 符号名还原
__cxa_get_globals            0x028140   ← 获取全局异常状态
__cxa_atexit                 extern     ← 注册退出处理
__cxa_finalize               extern     ← 析构处理
__gxx_personality_v0         0x03C628   ← C++异常个性函数

# 跳转桩(j_前缀)
j_.__cxa_call_unexpected     0x027A10
j_.__cxa_call_unexpected_0   0x027B54
... (共10个跳转桩)

4. RTTI 和动态类型(C++ 运行时)

text
__dynamic_cast               0x03E08C   ← dynamic_cast实现
std::type_info::~type_info() 0x03F1A0
std::bad_cast::bad_cast()    0x03F1B0
std::bad_typeid::bad_typeid()0x03F20C

5. Android 专有函数(libandroid.so / bionic)

text
__system_property_get    0x04A0C8   ← 读取系统属性
android_set_abort_message 0x04A040  ← 设置abort消息
getauxval               0x04A0C0   ← 获取辅助向量值
dl_iterate_phdr         0x04A0F8   ← 遍历程序头
__emutls_get_address    0x03F268   ← TLS模拟实现

6. POSIX 线程函数(libpthread.so)

text
pthread_mutex_lock       0x04A080
pthread_mutex_unlock     0x04A088
pthread_once             0x04A0A0
pthread_key_create       0x04A0B8
pthread_key_delete       0x04A0B0
pthread_getspecific      0x04A098
pthread_setspecific      0x04A0A8
pthread_rwlock_rdlock    0x04A100
pthread_rwlock_wrlock    0x04A0E8
pthread_rwlock_unlock    0x04A0F0

7. 日志函数(syslog)

text
openlog     0x04A048
syslog      0x04A050
closelog    0x04A058

三、汇总对比表

text
┌─────────────────────┬──────────┬──────────────────────────────┐
│     函数类型         │  数量    │         来源库               │
├─────────────────────┼──────────┼──────────────────────────────┤
│ 自定义JNI导出函数    │   1个    │ 用户代码                     │
│ 自定义内部函数(sub_) │  200+个  │ 用户代码(未命名)           │
│ C标准库函数          │  40+个   │ libc.so (bionic)             │
│ C++标准库函数        │  100+个  │ libc++.so (NDK)              │
│ C++ ABI异常函数      │  20+个   │ libgcc/libunwind             │
│ Android专有函数      │   5个    │ libandroid.so/bionic         │
│ POSIX线程函数        │  10个    │ libpthread.so                │
│ 日志函数             │   3个    │ libc.so (syslog)             │
└─────────────────────┴──────────┴──────────────────────────────┘

关键结论:

  • 真正的业务逻辑 只有 Java_com_example_helloworld_MainActivity_stringFromJNI 和 sub_1EE5C 这两个函数
  • 其余 sub_xxxx 函数大多是 C++标准库静态链接进来的实现代码
  • 整个 so 库将 libc++ 静态链接(函数在 .text 段而非 extern),这是 NDK 编译的典型特征

posted on 2026-04-05 07:54  GKLBB  阅读(4)  评论(0)    收藏  举报