逆向某app时,想用frida进行hook分析其执行流程,遇到了frida的反调试。这里记录一下出现问题的情况和反调试的实现.
Android8
frida12.11.18
windows10
使用frida -U注入app
结果如下
这里有两个com.shark.tracerpidapp名称的进程
我们直接进入adb查看进程
可以看到确实有两个进程,frida分不清你要注入哪个进程所以报出如上错误。
我们选择父进程进行注入
叫我们用root去执行,这里是没有用的。我们到adb看看这个父进程的TracerPid信息就知道了
至于为什么看TracerPid请移步文章 TracerPid反调试
可以看到父进程已经被子进程ATTACH,而frida也依赖于ptrace所以这里肯定注入不进去
我们不要让frida注入,而是使用frida启动app,使用-f选项,我们告诉Frida注入Zygote并开始启动应用程序
还有一种打补丁的方式,在下面参考中有。这里就不再赘述。
这个反调试其实就是用了 TracerPid反调试 的原理,但是在这里有一些不一样。
1:这里是子进程ATTACH父进程
2:在Android8中ptrace(PTRACE_TRACEME, 0, 0, 0)虽然返回的不是-1但是无法成功
所以我们这里要使用ptrace(PTRACE_ATTACH, parent, 0, 0)来实现。
PTRACE_ATTACH参数
ptrace(PTRACE_ATTACH,pid)
跟踪指定pid 进程。pid表示被跟踪进程。被跟踪进程将成为当前进程的子进程,并进入中止状态
PTRACE_CONT参数
ptrace(PTRACE_CONT, pid, 0, signal)
继续执行。pid表示被跟踪的子进程,signal为0则忽略引起调试进程中止的信号,若不为0则继续处理信号signal
先使用PTRACE_ATTACH进行附加,这时候被附加进程会阻塞。再使用PTRACE_CONT继续执行被附加的进程。为了确保PTRACE_CONT能被执行我们在PTRACE_ATTACH完后要马上wait阻塞当前线程。当附加成功后wait阻塞解除就能执行到PTRACE_CONT了
Android APP破解利器Frida之反调试对抗
ptrace使用简介
微软提供的API,随时在自己的程序中调用IsDebuggerPresent都可以检测出自己的程序是否被调试.先在vc++ 6.0 创建一个控制台测试程序 代码如下:
#include <windows.h>
typedef BOOL ( _stdcall *LPAPI_IDP)(VOID)
int main(int argc, char* argv[])
{
HMODULE hModule = LoadLibrary("Kernel32") // 加载模块Kernel32
if (hModule == NULL)
{
ExitProcess(0) // 如果发现程序被调试 直接退出进程
}
LPAPI_IDP IsDebuggerPresent = GetProcAddress(hModule, "IsDebuggerPresent") // 获取下地址
if (IsDebuggerPresent == NULL)
{
ExitProcess(0) // 如果发现程序被调试 直接退出进程
}
if (*(BYTE *)IsDebuggerPresent == 0xcc || // 调用前检测下是否被下了断点
*(BYTE *)IsDebuggerPresent != 0x64 ||
IsDebuggerPresent()) // 调用
{
ExitProcess(0) // 如果发现程序被调试 直接退出进程
}
// 如果程序能执行到这里 说明程序没有被调试状态
MessageBox(NULL, "Antidebug", NULL, MB_OK)
return 0
}
按F5调试运行 就会发现 程序直接推出.
单步跟踪可以测试到调用IsDebuggerPresent以后程序退出.
1.程序窗口句柄检测原理:用FindWindow函数查找具有相同窗口类名和标题的窗口,如果找到就说明有OD在运行
//********************************************
//通过查找窗口类名来实现检测OllyDBG
//********************************************
function AntiLoader():Boolean
const
OllyName='OLLYDBG'
var
Hwnd:Thandle
begin
Hwnd:=FindWindow(OllyName,nil)
if Hwnd<>0 then
Result:=True
else
Result:=False
end
procedure TForm1.FormCreate(Sender: TObject)
begin
if AntiLoader then
MessageBox(Handle,'找到调试器!','提示',MB_OK+MB_ICONINFORMATION)
else
MessageBox(Handle,'未找到调试器!','提示',MB_OK+MB_ICONINFORMATION)
end
2.用线程环境块检测
原理:用ring3级下的调试器对可执行程序进行调试时,调试器会把被调试的可执行程序作为一个子线程进行跟踪.这时被调试的可执行程序的PEB结构偏移0x02处的BeingDebugged的值为1,如果可执行程序未被调试,则值为0,所以可以利用这个值来检测程序是否被ring3级下的调试器调试
//***************************************
//使用PEB结构检测OllyDBG
//***************************************
function AntiLoader():Boolean//检测调试器
var
YInt,NInt:Integer
begin
asm
mov eax,fs:[$30]
//获取PEB偏移2h处BeingDebugged的值
movzx eax,byte ptr[eax+$2]
or al,al
jz @No
jnz @Yes
@No:
mov NInt,1
@Yes:
Mov YInt,1
end
if YInt=1 then
Result:=True
if NInt=1 then
Result:=False
end
procedure TForm1.FormCreate(Sender: TObject)
begin
if AntiLoader then
MessageBox(Handle,'发现调试器!','提示',MB_OK+MB_ICONINFORMATION)
else
MessageBox(Handle,'未发现调试器!','提示',MB_OK+MB_ICONINFORMATION)
end
3.用API函数IsDebuggerPresent检测
原理: *** 作系统将调试对象设置为在特殊环境中运行,而kernel32.dll中的API函数IsDebuggerPresent的功能是用于判断进程是否处于调试环境中,这样就可以利用这个API函数来查看进程是否在调试器中执行
//****************************************
//利用IsDebuggerPresent函数检测OllyDBG
//****************************************
function AntiLoader():Boolean
var
isDebuggerPresent: function:Boolean
Addr: THandle
begin
Addr := LoadLibrary('kernel32.dll')
isDebuggerPresent := GetProcAddress(Addr, 'IsDebuggerPresent')
if isDebuggerPresent then
Result:=True
else
Result:=False
end
procedure TForm1.FormCreate(Sender: TObject)
begin
if AntiLoader then
MessageBox(Handle,'发现调试器!','提示',MB_OK+MB_ICONINFORMATION)
else
MessageBox(Handle,'未发现提示器!','提示',MB_OK+MB_ICONINFORMATION)
end
4.检查程序的父进程
原理:Windows *** 作系统下的GUI可执行程序的父进程都是explorer.exe(CUI可执行程序的父进程是CMD.exe,系统服务的父进程是Service.exe,在实际使用的时候需要根据自己的程序类型来选择父进程实现反跟踪),而正被调试器OD调试的程序的父进程是调试器的执行程序ollydbg.exe而不是别的.所以可以利用检查父进程是否为explorer.exe的方法来检测OD.
//***************************************************
//检查父进程来检测OllyDBG
//***************************************************
function AntiLoader():Boolean
const
ParentName='\EXPLORER.EXE'
var
hSnap,hProcess:THandle
szBuffer:array[0..MAX_PATH] of char
FileName:array[0..MAX_PATH] of char
Process32:PROCESSENTRY32
LoopFlag:BOOL
begin
////得到所有进程的列表快照
hSnap:=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
if hSnap=INVALID_HANDLE_VALUE then
begin
Result:=False
Exit
end
Process32.dwSize:=sizeof(PROCESSENTRY32)
//查找进程
LoopFlag:=Process32First(hSnap,Process32)
if LoopFlag=False then
begin
CloseHandle(hSnap)
Result:=False
Exit
end
while Integer(LoopFlag)<>0 do
begin
if Process32.th32ProcessID=GetCurrentProcessId() then
begin
hProcess:=OpenProcess(PROCESS_ALL_ACCESS,FALSE,Process32.th32ParentProcessID)
if hProcess<>0 then
begin
if GetModuleFileNameEx(hProcess,0,FileName,MAX_PATH)<>0 then
begin
//取得系统目录
GetWindowsDirectory(szBuffer,MAX_PATH)
//合并系统目录和\EXPLORER.EXE
StrCat(szBuffer,ParentName)
//转换成大写以后比较当前调试程序的进程是否为父进程
if UpperCase(String(FileName))<>UpperCase(String(szBuffer)) then
Result:=True
else
Result:=False
end
end
else
Result:=False
end
LoopFlag:=Process32Next(hSnap,Process32)
end
CloseHandle(hSnap)
end
procedure TForm1.FormCreate(Sender: TObject)
begin
if AntiLoader then
MessageBox(Handle,'发现调试器!','提示',MB_OK+MB_ICONINFORMATION)
else
MessageBox(Handle,'未发现调试器!','提示',MB_OK+MB_ICONINFORMATION)
end
5.检查STARTUPINFO结构
原理:Windows *** 作系统中的explorer.exe创建进程的时候会把STARTUPINFO结构中的值设为0,而非explorer.exe创建进程的时候会忽略这个结构中的值,也就是结构中的值不为0,所以可以利用这个来判断OD是否在调试程序.
/************************************************
//通过检测STARTUPINFO结构来检测OllyDbg
//************************************************
function AntiLoader():Boolean
var
Info:STARTUPINFO
begin
GetStartupInfo(Info)
if (Info.dwX<>0) or (Info.dwY<>0) or (Info.dwXCountChars<>0) or (Info.dwYCountChars<>0) or
(Info.dwFillAttribute<>0) or (Info.dwXSize<>0) or (Info.dwYSize<>0) then
Result:=True
else
Result:=False
end
procedure TMainFrm.FormCreate(Sender: TObject)
begin
if AntiLoader then
MessageBox(Handle,'发现调试器!','提示',MB_OK)
else
MessageBox(Handle,'未发现调试器!','提示',MB_OK)
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)