指针是C/C++高性能的独门绝技,但是用不好也就成了稳定性的破坏之神,必须要养成良好的编码习惯。
IDA Pro 7.7 SP1
下载地址(百度网盘):链接: https://pan.baidu.com/s/1_QPXda0zg0joxfxivFzUpw 提取码: 7np1
1、双击下载后的IDAPro170914.dmg,打开如下安装界面,然后将左侧的【IDA Pro 7.0】拉到右侧应用程序即可:
2、安装完成后,直接双击打开可能出现如下问题:
解决方案如下:
如果出现弹窗提示您没有权限来打开应用程序“ida64”。请联系您的电脑或网络管理员以获得帮助。这是因为Mac系统无法直接启动64位应用程序,可以直接到安装目录下双击启动:
cd /Applications/IDA Pro 7.0open .
然后鼠标右键点击ida64,选择“显示包内容”,进入“Contents/MacOS”,右键点击ida64,选择“打开”。
打开后如果弹出“Oops, IDA has almost crashed!”,这是第三方输入法导致的,需要切换到英文输入法。
为方便说明,写一个测试程序,包含ida_crash.h、ida_crash.cc、ida_crash_test.cc、CMakeLists.txt四个文件:
ida_crash.h:
#include <string>class IdaCrash {public:std::string test();};
ida_crash.cc:
#include "ida_crash.h"std::string IdaCrash::test() {const char* data = getenv("IDA_CRASH_TEST");std::string str = data;return str;}
ida_crash_test.cc:
#include "ida_crash.h"#include <csignal>#include <execinfo.h>#include <iostream>std::string DumpBacktrace() {const int32_t MAX_STACK = 100;void *buffer[MAX_STACK] = {0};int32_t n = ::backtrace(buffer, MAX_STACK);if (n <= 0) {return std::string("backtrace fail: " + std::to_string(n));}char **symbols = ::backtrace_symbols(buffer, n);if (symbols == nullptr) {return std::string("backtrace fail: no symbols");}std::string bt_stack = "\n";for (int32_t i = 1; i < n; ++i) {bt_stack += (" " + std::string(symbols[i]) + "\n");}::free(symbols);return bt_stack;}void SignalHandler(int sigval) {switch (sigval) {case SIGABRT:case SIGBUS:case SIGFPE:case SIGHUP:case SIGQUIT:case SIGSEGV:case SIGTERM:case SIGILL:std::cout << "backtrace:\n" << DumpBacktrace() << std::endl;std::signal(sigval, SIG_DFL);std::raise(sigval);break;case SIGINT:break;default:break;}}void RegSigCallBack() {std::signal(SIGABRT, SignalHandler);std::signal(SIGBUS, SignalHandler);std::signal(SIGFPE, SignalHandler);std::signal(SIGHUP, SignalHandler);std::signal(SIGINT, SignalHandler);std::signal(SIGQUIT, SignalHandler);std::signal(SIGSEGV, SignalHandler);std::signal(SIGTERM, SignalHandler);std::signal(SIGILL, SignalHandler);}int main(int argc, char** argv) {RegSigCallBack();IdaCrash test;test.test();return 0;}
CMakeLists.txt:
cmake_minimum_required(VERSION 3.10)project(ida_crash_test)add_library(ida_crash ida_crash.cc)add_executable(ida_crash_test ida_crash_test.cc)target_link_libraries(ida_crash_test ida_crash)
编译后执行./ida_crash_test,打印出crash堆栈如下:
backtrace:./ida_crash_test(+0x1d26) [0x557b70a01d26]/lib/x86_64-linux-gnu/libc.so.6(+0x3ef10) [0x7f9e73932f10]/lib/x86_64-linux-gnu/libc.so.6(gsignal+0xc7) [0x7f9e73932e87]/lib/x86_64-linux-gnu/libc.so.6(abort+0x141) [0x7f9e739347f1]/usr/lib/x86_64-linux-gnu/libstdc++.so.6(+0x8c957) [0x7f9e73f89957]/usr/lib/x86_64-linux-gnu/libstdc++.so.6(+0x92ae6) [0x7f9e73f8fae6]/usr/lib/x86_64-linux-gnu/libstdc++.so.6(+0x92b21) [0x7f9e73f8fb21]/usr/lib/x86_64-linux-gnu/libstdc++.so.6(+0x92d54) [0x7f9e73f8fd54]/usr/lib/x86_64-linux-gnu/libstdc++.so.6(+0x8e79f) [0x7f9e73f8b79f]/usr/lib/x86_64-linux-gnu/libstdc++.so.6(_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_M_constructIPKcEEvT_S8_St20forward_iterator_tag+0xcd) [0x7f9e740242dd]/home/work/ida_crash_test/build/libida_crash.so(_ZN8IdaCrash4testB5cxx11Ev+0x53) [0x7f9e7428695d]./ida_crash_test(+0x1e80) [0x557b70a01e80]/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xe7) [0x7f9e73915c87]./ida_crash_test(+0x186a) [0x557b70a0186a]
上述堆栈清楚显示crash位置为libida_crash.so(_ZN8IdaCrash4testB5cxx11Ev+0x53) [0x7f9e7428695d]
1、确定崩溃位置
通过堆栈分析,crash位置为libida_crash.so(_ZN8IdaCrash4testB5cxx11Ev+0x53) [0x7f9e7428695d],其中小括号表示偏移地址(_ZN8IdaCrash4testB5cxx11Ev+0x53,有的堆栈没有+号前面的部分),中括号表示虚拟地址(0x7f9e7428695d)
2、打开IDA分析软件,并加载libida_crash.so:
3、等待加载完成(文件很大时可能加载时间很长),完成后显示如下界面:
4、在左侧窗口中找到_ZN8IdaCrash4testB5cxx11Ev这个符号,双击,然后按F5键进行反编译(Mac下为左下角Fn功能键同时按最上方的F5)
5、此时右侧窗口显示的就是反汇编代码,里面调用了getenv接口,返回一个指针v3,指针未做判空检查直接赋值给一个std::string变量导致crash。
6、如果堆栈中的便宜地址只有0x开头的数字,则直接可以在IDA软件中按g键输入地址跳转到该位置,然后按F5键反编译即可,如下图所示: