指针是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.0
open .
然后鼠标右键点击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键反编译即可,如下图所示: