objective-c runtime安全措施之三:反汇编(inline编译方式)
《O'Reilly.Hacking.and.Securing.iOS.Applications>>读书笔记
反汇编:通过优化编译器选项、去除符号表来复杂化编译后生成的汇编代码(使用反汇编工具结合动态调试工具弄清并篡改程序逻辑)
方法1:采用inline函数
原理:设置inline属性、static属性,可以使得编译后生成的目标代码在反汇编成汇编代码时,不容易阅读,弄清其中的逻辑,因为inline会导致汇编代码中是直接将inline函数的函数体拷贝到main中,而不是清晰的call调用;static属性,则会让编译生成的二进制代码中,没有清晰的符号表,同样使得攻击者很难通过逆向弄清楚程序逻辑。
例子1. non-inline函数和其反汇编代码
#include <stdlib.h>
int is_session_valid(int session_id) {//session_id为偶数返回1,为奇数返回0
if (session_id % 2 == 0) {
return 1;
} else {
return 0;
}
}
int main( ) {
int session = 3;
if (! is_session_valid(session))
return EXIT_FAILURE;
/*
* Do something else
*/
if (! is_session_valid(session))
return EXIT_FAILURE;
/*
* Do something else
*/
if (! is_session_valid(session))
return EXIT_FAILURE;
return EXIT_SUCCESS;
}
编译$ gcc -o securitycheck securitycheck.c
使用otool工具反汇编该程序,为了方便阅读start函数已经被移除了。
$ otool -tV securitycheck
_is_session_valid:
0000000100000e70 pushq %rbp
0000000100000e71 movq %rsp,%rbp
0000000100000e74 movl %edi,0xfc(%rbp)
0000000100000e77 movl 0xfc(%rbp),%eax
0000000100000e7a andl $0x01,%eax
0000000100000e7d cmpl $0x00,%eax
0000000100000e80 jne 0x100000e8b
0000000100000e82 movl $0x00000001,0xf4(%rbp)
0000000100000e89 jmp 0x100000e92
0000000100000e8b movl $0x00000000,0xf4(%rbp)
0000000100000e92 movl 0xf4(%rbp),%eax
0000000100000e95 movl %eax,0xf8(%rbp)
0000000100000e98 movl 0xf8(%rbp),%eax
0000000100000e9b popq %rbp
0000000100000e9c ret
0000000100000e9d nopl (%rax)
_main:
0000000100000ea0 pushq %rbp
0000000100000ea1 movq %rsp,%rbp
0000000100000ea4 subq $0x10,%rsp
0000000100000ea8 movl $0x00000003,0xf4(%rbp)
0000000100000eaf movl 0xf4(%rbp),%eax
0000000100000eb2 movl %eax,%edi
0000000100000eb4 callq _is_session_valid
0000000100000eb9 movl %eax,%ecx
0000000100000ebb cmpl $0x00,%ecx
0000000100000ebe jne 0x100000ec9
0000000100000ec0 movl $0x00000001,0xf8(%rbp)
0000000100000ec7 jmp 0x100000f04
0000000100000ec9 movl 0xf4(%rbp),%eax
0000000100000ecc movl %eax,%edi
0000000100000ece callq _is_session_valid
0000000100000ed3 movl %eax,%ecx
0000000100000ed5 cmpl $0x00,%ecx
0000000100000ed8 jne 0x100000ee3
0000000100000eda movl $0x00000001,0xf8(%rbp)
0000000100000ee1 jmp 0x100000f04
0000000100000ee3 movl 0xf4(%rbp),%eax
0000000100000ee6 movl %eax,%edi
0000000100000ee8 callq _is_session_valid
0000000100000eed movl %eax,%ecx
0000000100000eef cmpl $0x00,%ecx
0000000100000ef2 jne 0x100000efd
0000000100000ef4 movl $0x00000001,0xf8(%rbp)
0000000100000efb jmp 0x100000f04
0000000100000efd movl $0x00000000,0xf8(%rbp)
0000000100000f04 movl 0xf8(%rbp),%eax
0000000100000f07 movl %eax,0xfc(%rbp)
0000000100000f0a movl 0xfc(%rbp),%eax
0000000100000f0d addq $0x10,%rsp
0000000100000f11 popq %rbp
0000000100000f12 ret
如你所知,is_sesssion_valid函数和main函数的定义是非常清晰的。攻击者是非常容易通过动态调试设置断点的方法修改is_session_valid函数的返回值来绕过检查。
$ gdb -q ./securitycheck
Reading symbols for shared libraries .. done
(gdb) break is_session_valid
Breakpoint 1 at 0x100000e77
(gdb) commands
Type commands for when breakpoint 1 is hit, one per line.
End with a line saying just "end".
>return 1
>continue
>end
(gdb) r
Starting program: /Users/jonz/securitycheck
Reading symbols for shared libraries +........................ done
Breakpoint 1, 0x0000000100000e77 in is_session_valid ()
Breakpoint 1, 0x0000000100000e77 in is_session_valid ()
Breakpoint 1, 0x0000000100000e77 in is_session_valid ()
Program exited normally.
(gdb)
程序在第一次调用is_session_valid时不会退出,因为调试器将is_session_valid函数值改成了1.
例子2:inline函数和其反汇编代码
#include <stdlib.h>
inline int is_session_valid(int session_id) {
if (session_id % 2 == 0) {
return 1;
} else {
return 0;
}
}
int main( ) {
int session = 3;
if (! is_session_valid(session))
return EXIT_FAILURE;
/*
* Do something else
*/
if (! is_session_valid(session))
return EXIT_FAILURE;
/*
* Do something else
*/
if (! is_session_valid(session))
return EXIT_FAILURE;
return EXIT_SUCCESS;
}
编译, -finline-functions告诉编译器尽可能的采用inline编译方式;-Winline告诉编译器在不能使用inline编译方式编译时报错
$ gcc -o securitycheck securitycheck.c -finline-functions -Winline
使用otool工具反汇编该程序
$ otool -tV securitycheck
_is_session_valid:
0000000100000e20 pushq %rbp
0000000100000e21 movq %rsp,%rbp
0000000100000e24 movl %edi,0xfc(%rbp)
0000000100000e27 movl 0xfc(%rbp),%eax
0000000100000e2a andl $0x01,%eax
0000000100000e2d cmpl $0x00,%eax
0000000100000e30 jne 0x100000e3b
0000000100000e32 movl $0x00000001,0xf4(%rbp)
0000000100000e39 jmp 0x100000e42
0000000100000e3b movl $0x00000000,0xf4(%rbp)
0000000100000e42 movl 0xf4(%rbp),%eax
0000000100000e45 movl %eax,0xf8(%rbp)
0000000100000e48 movl 0xf8(%rbp),%eax
0000000100000e4b popq %rbp
0000000100000e4c ret
0000000100000e4d nopl (%rax)
_main:
0000000100000e50 pushq %rbp
0000000100000e51 movq %rsp,%rbp
0000000100000e54 movl $0x00000003,0xd0(%rbp)
0000000100000e5b movl 0xd0(%rbp),%eax
0000000100000e5e movl %eax,0xe4(%rbp)
0000000100000e61 movl 0xe4(%rbp),%eax
0000000100000e64 andl $0x01,%eax
0000000100000e67 cmpl $0x00,%eax
0000000100000e6a jne 0x100000e75
0000000100000e6c movl $0x00000001,0xdc(%rbp)
0000000100000e73 jmp 0x100000e7c
0000000100000e75 movl $0x00000000,0xdc(%rbp)
0000000100000e7c movl 0xdc(%rbp),%eax
0000000100000e7f movl %eax,0xe0(%rbp)
0000000100000e82 movl 0xe0(%rbp),%eax
0000000100000e85 cmpl $0x00,%eax
0000000100000e88 jne 0x100000e93
0000000100000e8a movl $0x00000001,0xd4(%rbp)
0000000100000e91 jmp 0x100000f0a
0000000100000e93 movl 0xd0(%rbp),%eax
0000000100000e96 movl %eax,0xfc(%rbp)
0000000100000e99 movl 0xfc(%rbp),%eax
0000000100000e9c andl $0x01,%eax
0000000100000e9f cmpl $0x00,%eax
0000000100000ea2 jne 0x100000ead
0000000100000ea4 movl $0x00000001,0xf4(%rbp)
0000000100000eab jmp 0x100000eb4
0000000100000ead movl $0x00000000,0xf4(%rbp)
0000000100000eb4 movl 0xf4(%rbp),%eax
0000000100000eb7 movl %eax,0xf8(%rbp)
0000000100000eba movl 0xf8(%rbp),%eax
0000000100000ebd cmpl $0x00,%eax
0000000100000ec0 jne 0x100000ecb
0000000100000ec2 movl $0x00000001,0xd4(%rbp)
0000000100000e91 jmp 0x100000f0a
0000000100000e93 movl 0xd0(%rbp),%eax
0000000100000e96 movl %eax,0xfc(%rbp)
0000000100000e99 movl 0xfc(%rbp),%eax
0000000100000e9c andl $0x01,%eax
0000000100000e9f cmpl $0x00,%eax
0000000100000ea2 jne 0x100000ead
0000000100000ea4 movl $0x00000001,0xf4(%rbp)
0000000100000eab jmp 0x100000eb4
0000000100000ead movl $0x00000000,0xf4(%rbp)
0000000100000eb4 movl 0xf4(%rbp),%eax
0000000100000eb7 movl %eax,0xf8(%rbp)
0000000100000eba movl 0xf8(%rbp),%eax
0000000100000ebd cmp
补充:综合编程 , 安全编程 ,