感谢2023年的陪伴,2024年继续加油^_^
最近真的太忙了,天天打仗一样,感谢大家的支持和关注,继续加油!该系列文章将系统整理和深入学习系统安全、逆向分析和恶意代码检测,文章会更加聚焦,更加系统,更加深入,也是作者的慢慢成长史。漫漫长征路,偏向虎山行。享受过程,一起奋斗~
-
一.PE文件格式
-
二.PE文件格式解析
-
1.010Editor解析PE文件
-
2.Ollydbg动态调试程序
-
三.Python获取时间戳
-
四.时间戳判断来源地区
-
1.UTC时间转换
-
2.时区APT溯源案例
-
3.时间戳分析
-
五.总结
作者的github资源:
-
逆向分析:
-
https://github.com/eastmountyxz/
SystemSecurity-ReverseAnalysis
-
网络安全:
-
https://github.com/eastmountyxz/
NetworkSecuritySelf-study
一.PE文件格式
二.PE文件格式解析
1.010Editor解析PE文件
typedef struct _IMAGE_OPTIONAL_HEADER {
WORD Magic; /*机器型号,判断是PE是32位还是64位*/
BYTE MajorLinkerVersion; /*连接器版本号高版本*/
BYTE MinorLinkerVersion; /*连接器版本号低版本,组合起来就是 5.12 其中5是高版本,C是低版本*/
DWORD SizeOfCode; /*代码节的总大小(512为一个磁盘扇区)*/
DWORD SizeOfInitializedData; /*初始化数据的节的总大小,也就是.data*/
DWORD SizeOfUninitializedData; /*未初始化数据的节的大小,也就是 .data ? */
DWORD AddressOfEntryPoint; /*程序执行入口(OEP) RVA(相对偏移)*/
DWORD BaseOfCode; /*代码的节的起始RVA(相对偏移)也就是代码区的偏移,偏移+模块首地址定位代码区*/
DWORD BaseOfData; /*数据结的起始偏移(RVA),同上*/
DWORD ImageBase; /*程序的建议模块基址(意思就是说作参考用的,模块地址在哪里)*/
DWORD SectionAlignment; /*内存中的节对齐*/
DWORD FileAlignment; /*文件中的节对齐*/
WORD MajorOperatingSystemVersion; /*操作系统版本号高位*/
WORD MinorOperatingSystemVersion; /*操作系统版本号低位*/
WORD MajorImageVersion; /*PE版本号高位*/
WORD MinorImageVersion; /*PE版本号低位*/
WORD MajorSubsystemVersion; /*子系统版本号高位*/
WORD MinorSubsystemVersion; /*子系统版本号低位*/
DWORD Win32VersionValue; /*32位系统版本号值,注意只能修改为4 5 6表示操作系统支持nt4.0 以上,5的话依次类推*/
DWORD SizeOfImage; /*整个程序在内存中占用的空间(PE映尺寸)*/
DWORD SizeOfHeaders; /*所有头(头的结构体大小)+节表的大小*/
DWORD CheckSum; /*校验和,对于驱动程序,可能会使用*/
WORD Subsystem; /*文件的子系统 :重要*/
WORD DllCharacteristics; /*DLL文件属性,也可以成为特性,可能DLL文件可以当做驱动程序使用*/
DWORD SizeOfStackReserve; /*预留的栈的大小*/
DWORD SizeOfStackCommit; /*立即申请的栈的大小(分页为单位)*/
DWORD SizeOfHeapReserve; /*预留的堆空间大小*/
DWORD SizeOfHeapCommit; /*立即申请的堆的空间的大小*/
DWORD LoaderFlags; /*与调试有关*/
DWORD NumberOfRvaAndSizes; /*下面的成员,数据目录结构的项目数量*/
IMAGE_DATA_DIRECTORY DataDirectory[16]; /*数据目录,默认16个,16是宏,这里方便直接写成16*/
} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;
2.Ollydbg动态调试程序
三.Python获取时间戳
import pefile
import os,string,shutil,re
PEfile_Path = "MFCApplication.exe"
pe = pefile.PE(PEfile_Path)
print(type(pe))
print(pe)
Warnings----------
Byte 0xcc makes up 17.8750% of the file's contents. This may indicate truncation / malformation.
Suspicious flags set for section 0. Both IMAGE_SCN_MEM_WRITE and IMAGE_SCN_MEM_EXECUTE are set. This might indicate a packed executable.
----------DOS_HEADER----------
[IMAGE_DOS_HEADER]
0x0 0x0 e_magic: 0x5A4D
0x2 0x2 e_cblp: 0x90
0x4 0x4 e_cp: 0x3
0x6 0x6 e_crlc: 0x0
0x8 0x8 e_cparhdr: 0x4
0xA 0xA e_minalloc: 0x0
0xC 0xC e_maxalloc: 0xFFFF
0xE 0xE e_ss: 0x0
0x10 0x10 e_sp: 0xB8
0x12 0x12 e_csum: 0x0
0x14 0x14 e_ip: 0x0
0x16 0x16 e_cs: 0x0
0x18 0x18 e_lfarlc: 0x40
0x1A 0x1A e_ovno: 0x0
0x1C 0x1C e_res:
0x24 0x24 e_oemid: 0x0
0x26 0x26 e_oeminfo: 0x0
0x28 0x28 e_res2:
0x3C 0x3C e_lfanew: 0x108
----------NT_HEADERS----------
[IMAGE_NT_HEADERS]
0x108 0x0 Signature: 0x4550
----------FILE_HEADER----------
[IMAGE_FILE_HEADER]
0x10C 0x0 Machine: 0x14C
0x10E 0x2 NumberOfSections: 0xA
0x110 0x4 TimeDateStamp: 0x5EEC977D [Fri Jun 19 10:46:21 2020 UTC]
0x114 0x8 PointerToSymbolTable: 0x0
0x118 0xC NumberOfSymbols: 0x0
0x11C 0x10 SizeOfOptionalHeader: 0xE0
0x11E 0x12 Characteristics: 0x102
Flags: IMAGE_FILE_32BIT_MACHINE, IMAGE_FILE_EXECUTABLE_IMAGE
----------OPTIONAL_HEADER----------
[IMAGE_OPTIONAL_HEADER]
0x120 0x0 Magic: 0x10B
0x122 0x2 MajorLinkerVersion: 0xE
0x123 0x3 MinorLinkerVersion: 0x1A
0x124 0x4 SizeOfCode: 0x700C00
0x128 0x8 SizeOfInitializedData: 0x2F1E00
0x12C 0xC SizeOfUninitializedData: 0x0
0x130 0x10 AddressOfEntryPoint: 0x36CE65
0x134 0x14 BaseOfCode: 0x1000
0x138 0x18 BaseOfData: 0x1000
0x13C 0x1C ImageBase: 0x400000
0x140 0x20 SectionAlignment: 0x1000
0x144 0x24 FileAlignment: 0x200
0x148 0x28 MajorOperatingSystemVersion: 0x6
0x14A 0x2A MinorOperatingSystemVersion: 0x0
0x14C 0x2C MajorImageVersion: 0x0
0x14E 0x2E MinorImageVersion: 0x0
0x150 0x30 MajorSubsystemVersion: 0x6
0x152 0x32 MinorSubsystemVersion: 0x0
0x154 0x34 Reserved1: 0x0
0x158 0x38 SizeOfImage: 0xD54000
0x15C 0x3C SizeOfHeaders: 0x400
0x160 0x40 CheckSum: 0x0
0x164 0x44 Subsystem: 0x2
0x166 0x46 DllCharacteristics: 0x8140
0x168 0x48 SizeOfStackReserve: 0x100000
0x16C 0x4C SizeOfStackCommit: 0x1000
0x170 0x50 SizeOfHeapReserve: 0x100000
0x174 0x54 SizeOfHeapCommit: 0x1000
0x178 0x58 LoaderFlags: 0x0
0x17C 0x5C NumberOfRvaAndSizes: 0x10
DllCharacteristics: IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE, IMAGE_DLLCHARACTERISTICS_NX_COMPAT, IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE
Sections----------
[IMAGE_SECTION_HEADER]
0x200 0x0 Name: .textbss
0x208 0x8 Misc: 0x35B30B
0x208 0x8 Misc_PhysicalAddress: 0x35B30B
0x208 0x8 Misc_VirtualSize: 0x35B30B
0x20C 0xC VirtualAddress: 0x1000
0x210 0x10 SizeOfRawData: 0x0
0x214 0x14 PointerToRawData: 0x0
0x218 0x18 PointerToRelocations: 0x0
0x21C 0x1C PointerToLinenumbers: 0x0
0x220 0x20 NumberOfRelocations: 0x0
0x222 0x22 NumberOfLinenumbers: 0x0
0x224 0x24 Characteristics: 0xE00000A0
Flags: IMAGE_SCN_CNT_CODE, IMAGE_SCN_CNT_UNINITIALIZED_DATA, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE
Entropy: 0.000000 (Min=0.0, Max=8.0)
MD5 hash: d41d8cd98f00b204e9800998ecf8427e
hash: da39a3ee5e6b4b0d3255bfef95601890afd80709
hash: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
hash: cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e
....
Help on class PE in module pefile:
class PE(builtins.object)
| PE(name=None, data=None, fast_load=None)
|
| A Portable Executable representation.
|
| This class provides access to most of the information in a PE file.
|
| It expects to be supplied the name of the file to load or PE data
| to process and an optional argument 'fast_load' (False by default)
| which controls whether to load all the directories information,
| which can be quite time consuming.
|
| pe = pefile.PE('module.dll')
| pe = pefile.PE(name='module.dll')
|
| would load 'module.dll' and process it. If the data is already
| available in a buffer the same can be achieved with:
|
| pe = pefile.PE(data=module_dll_data)
|
| The "fast_load" can be set to a default by setting its value in the
| module itself by means, for instance, of a "pefile.fast_load = True".
| That will make all the subsequent instances not to load the
| whole PE structure. The "full_load" method can be used to parse
| the missing data at a later stage.
|
| Basic headers information will be available in the attributes:
|
| DOS_HEADER
| NT_HEADERS
| FILE_HEADER
| OPTIONAL_HEADER
|
| All of them will contain among their attributes the members of the
| corresponding structures as defined in WINNT.H
|
| The raw data corresponding to the header (from the beginning of the
| file up to the start of the first section) will be available in the
| instance's attribute 'header' as a string.
|
| The sections will be available as a list in the 'sections' attribute.
| Each entry will contain as attributes all the structure's members.
|
| Directory entries will be available as attributes (if they exist):
| (no other entries are processed at this point)
|
| DIRECTORY_ENTRY_IMPORT (list of ImportDescData instances)
| DIRECTORY_ENTRY_EXPORT (ExportDirData instance)
| DIRECTORY_ENTRY_RESOURCE (ResourceDirData instance)
| DIRECTORY_ENTRY_DEBUG (list of DebugData instances)
| DIRECTORY_ENTRY_BASERELOC (list of BaseRelocationData instances)
| DIRECTORY_ENTRY_TLS
| DIRECTORY_ENTRY_BOUND_IMPORT (list of BoundImportData instances)
|
| The following dictionary attributes provide ways of mapping different
| constants. They will accept the numeric value and return the string
| representation and the opposite, feed in the string and get the
| numeric constant:
|
| DIRECTORY_ENTRY
| IMAGE_CHARACTERISTICS
| SECTION_CHARACTERISTICS
| DEBUG_TYPE
| SUBSYSTEM_TYPE
| MACHINE_TYPE
| RELOCATION_TYPE
| RESOURCE_TYPE
| LANG
| SUBLANG
......
import pefile
import os,string,shutil,re
PEfile_Path = "MFCApplication.exe"
#解析PE文件
pe = pefile.PE(PEfile_Path)
print(type(pe))
print(pe)
#查看方法和属性
print(dir(pefile.PE))
for section in pe.sections:
print(section)
import pefile
import os,string,shutil,re
PEfile_Path = "MFCApplication.exe"
#解析PE文件
pe = pefile.PE(PEfile_Path)
print(type(pe))
print(pe)
#获取导入表信息
for item in pe.DIRECTORY_ENTRY_IMPORT:
print(item.dll)
for con in item.imports:
print(con.name)
print("") #换行
b'KERNEL32.dll'
b'RtlUnwind'
b'GetModuleHandleExW'
b'GetCommandLineA'
b'GetSystemInfo'
b'CreateThread'
...
b'USER32.dll'
b'DlgDirSelectExA'
b'FindWindowExA'
b'FindWindowA'
b'SetParent'
b'ChildWindowFromPointEx'
...
b'GDI32.dll'
b'CreateEllipticRgn'
b'CreateFontIndirectA'
b'CreateHatchBrush'
b'CreateICA'
b'CreatePalette'
b'CreatePen'
...
b'MSIMG32.dll'
b'AlphaBlend'
b'GradientFill'
b'TransparentBlt'
b'ADVAPI32.dll'
b'RegCloseKey'
b'RegQueryValueExA'
b'RegCreateKeyExA'
b'RegDeleteKeyA'
...
b'SHELL32.dll'
b'SHGetPathFromIDListA'
b'SHGetSpecialFolderLocation'
b'SHBrowseForFolderA'
b'SHGetDesktopFolder'
b'DragAcceptFiles'
...
b'COMCTL32.dll'
b'InitCommonControlsEx'
...
typedef struct _IMAGE_FILE_HEADER
{
+04h WORD Machine; // 运行平台
+06h WORD NumberOfSections; // 文件的区块数目
+08h DWORD TimeDateStamp; // 文件创建日期和时间
+0Ch DWORD PointerToSymbolTable; // 指向符号表(主要用于调试)
+10h DWORD NumberOfSymbols; // 符号表中符号个数(同上)
+14h WORD SizeOfOptionalHeader; // IMAGE_OPTIONAL_HEADER32 结构大小
+16h WORD Characteristics; // 文件属性
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
import pefile
import os,string,shutil,re
PEfile_Path = "MFCApplication.exe"
#解析PE文件
pe = pefile.PE(PEfile_Path, fast_load=True)
print(type(pe))
print(pe)
#显示DOS_HEADER
print(pe.DOS_HEADER,"n")
#显示NT_HEADERS
print(pe.NT_HEADERS,"n")
#显示FILE_HEADER
print(pe.FILE_HEADER,"n")
#显示OPTIONAL_HEADER
print(pe.OPTIONAL_HEADER,"n")
import pefile
import os,string,shutil,re
PEfile_Path = "MFCApplication.exe"
#解析PE文件
pe = pefile.PE(PEfile_Path, fast_load=True)
print(type(pe))
print(pe)
print(pe.get_imphash())
#显示DOS_HEADER
dh = pe.DOS_HEADER
#显示NT_HEADERS
nh = pe.NT_HEADERS
#显示FILE_HEADER
fh = pe.FILE_HEADER
#显示OPTIONAL_HEADER
oh = pe.OPTIONAL_HEADER
print(type(fh)) #<class 'pefile.Structure'>
print(str(fh))
#通过正则表达式获取时间
p = re.compile(r'[[](.*?)[]]', re.I|re.S|re.M) #最小匹配
res = re.findall(p, str(fh))
print(res[1]) #第一个值是IMAGE_FILE_HEADER
# Fri Jun 19 10:46:21 2020 UTC
'pefile.PE'>
Squeezed text(347 lines).
'pefile.Structure'>
[IMAGE_FILE_HEADER]
0x10C 0x0 Machine: 0x14C
0x10E 0x2 NumberOfSections: 0xA
0x110 0x4 TimeDateStamp: 0x5EEC977D [Fri Jun 19 10:46:21 2020 UTC]
0x114 0x8 PointerToSymbolTable: 0x0
0x118 0xC NumberOfSymbols: 0x0
0x11C 0x10 SizeOfOptionalHeader: 0xE0
0x11E 0x12 Characteristics: 0x102
Fri Jun 19 10:46:21 2020 UTC
四.时间戳判断来源地区
1.UTC时间转换
import pefile
import time
import datetime
import os,string,shutil,re
PEfile_Path = "MFCApplication.exe"
#----------------------------------第一步 解析PE文件-------------------------------
pe = pefile.PE(PEfile_Path, fast_load=True)
print(type(pe))
print(pe)
print(pe.get_imphash())
#显示DOS_HEADER
dh = pe.DOS_HEADER
#显示NT_HEADERS
nh = pe.NT_HEADERS
#显示FILE_HEADER
fh = pe.FILE_HEADER
#显示OPTIONAL_HEADER
oh = pe.OPTIONAL_HEADER
print(type(fh)) #<class 'pefile.Structure'>
print(str(fh))
#----------------------------------第二步 获取UTC时间-------------------------------
#通过正则表达式获取时间
p = re.compile(r'[[](.*?)[]]', re.I|re.S|re.M) #最小匹配
res = re.findall(p, str(fh))
print(res[1]) #第一个值是IMAGE_FILE_HEADER
res_time = res[1].replace(" UTC","")
# Fri Jun 19 10:46:21 2020 UTC
#获取当前时间
t = time.ctime()
print(t) # Thu Jul 16 20:42:18 2020
final_time = datetime.datetime.strptime(res_time, '%a %b %d %H:%M:%S %Y')
print(final_time)
# 2020-06-19 10:46:21
2.时区APT溯源案例
3.时间戳分析
import pefile
import time
import warnings
import datetime
import os,string,shutil,re
#忽略警告
warnings.filterwarnings("ignore")
PEfile_Path = "MFCApplication.exe"
#----------------------------------第一步 解析PE文件-------------------------------
pe = pefile.PE(PEfile_Path, fast_load=True)
print(type(pe))
print(pe)
print(pe.get_imphash())
#显示DOS_HEADER
dh = pe.DOS_HEADER
#显示NT_HEADERS
nh = pe.NT_HEADERS
#显示FILE_HEADER
fh = pe.FILE_HEADER
#显示OPTIONAL_HEADER
oh = pe.OPTIONAL_HEADER
print(type(fh)) #<class 'pefile.Structure'>
print(str(fh))
#----------------------------------第二步 获取UTC时间-------------------------------
#通过正则表达式获取时间
p = re.compile(r'[[](.*?)[]]', re.I|re.S|re.M) #最小匹配
res = re.findall(p, str(fh))
print(res[1]) #第一个值是IMAGE_FILE_HEADER
res_time = res[1].replace(" UTC","")
# Fri Jun 19 10:46:21 2020 UTC
#获取当前时间
t = time.ctime()
print(t,"n") # Thu Jul 16 20:42:18 2020
utc_time = datetime.datetime.strptime(res_time, '%a %b %d %H:%M:%S %Y')
print("UTC Time:", utc_time)
# 2020-06-19 10:46:21
#----------------------------------第三步 全球时区转换-------------------------------
#http://zh.thetimenow.com/india
#UTC时间比北京时间晚八个小时 故用timedelta方法加上八个小时
china_time = datetime.datetime.strptime(res_time, '%a %b %d %H:%M:%S %Y') + datetime.timedelta(hours=8)
print("China Time:",china_time)
#美国 UTC-5
america_time = datetime.datetime.strptime(res_time, '%a %b %d %H:%M:%S %Y') - datetime.timedelta(hours=5)
print("America Time:",america_time)
#印度 UTC+5
india_time = datetime.datetime.strptime(res_time, '%a %b %d %H:%M:%S %Y') + datetime.timedelta(hours=5)
print("India Time:",india_time)
#澳大利亚 UTC+10
australia_time = datetime.datetime.strptime(res_time, '%a %b %d %H:%M:%S %Y') + datetime.timedelta(hours=10)
print("Australia Time",australia_time)
#俄罗斯 UTC+3
russia_time = datetime.datetime.strptime(res_time, '%a %b %d %H:%M:%S %Y') + datetime.timedelta(hours=3)
print("Russia Time",russia_time)
#英国 UTC+0
england_time = datetime.datetime.strptime(res_time, '%a %b %d %H:%M:%S %Y')
print("England Time",england_time)
#日本 UTC+9
japan_time = datetime.datetime.strptime(res_time, '%a %b %d %H:%M:%S %Y') + datetime.timedelta(hours=9)
print("Japan Time",england_time)
#德国 UTC+1
germany_time = datetime.datetime.strptime(res_time, '%a %b %d %H:%M:%S %Y') + datetime.timedelta(hours=1)
print("Germany Time",germany_time)
#法国 UTC+1
france_time = datetime.datetime.strptime(res_time, '%a %b %d %H:%M:%S %Y') + datetime.timedelta(hours=1)
print("France Time",france_time)
#加拿大 UTC-5
canada_time = datetime.datetime.strptime(res_time, '%a %b %d %H:%M:%S %Y') - datetime.timedelta(hours=5)
print("Canada Time:",canada_time)
#越南 UTC+7
vietnam_time = datetime.datetime.strptime(res_time, '%a %b %d %H:%M:%S %Y') + datetime.timedelta(hours=7)
print("Vietnam Time:",vietnam_time)
五.总结
前文回顾(下面的超链接可以点击喔):
-
[系统安全] 五十四.恶意软件分析 (6)PE文件解析及利用Python获取样本时间戳详解
原文始发于微信公众号(娜璋AI安全之家):[系统安全] 五十四.恶意软件分析 (6)PE文件解析及利用Python获取样本时间戳详解