Internet of things devices are facing unprecedented threats. The object of malware attack is usually the network device with poor security or improper configuration. Hardware manufacturers and security industry are trying to study all kinds of attacks to make more secure products. "Attacks against Internet of things devices" and "malware analysis" are the two biggest challenges in this process.
At present, "Internet of things devices" and "malware" are running in different operating systems and CPU architectures at the same time. Reverse engineers need to understand all CPU architectures, which greatly reduces the analysis efficiency. At the same time, many analysis tools that can't be updated in time are in short supply in the face of endless new attacks.
At present, many binary analysis tools (system simulation, user mode simulation, binary instrumentation tools and sandbox) are only for a single type of operating system or CPU architecture, and it is almost impossible for these tools to share information or cross reference data. This is the difficulty of reverse engineering.
[1] According to SonicWALL's research, in 2018, malware attacks increased significantly, reaching a record high of 10.52 billion, and cyber criminals used new threat strategies.
Kirin framework aims to change the current situation of Internet of things security research, malware analysis and reverse engineering. Our goal is to build a cross platform, multi architecture analysis framework, not just a reverse tool. Kirin framework has powerful functions, such as code interception and arbitrary code injection before or during binary execution. It can also patch target binaries during execution.
Kirin framework is an open source tool written in Python. Python is a simple programming language commonly used by reverse engineers, which greatly reduces the threshold of secondary development.
Kirin framework is not only a simulation platform or reverse engineering tool. It also combines binary instrumentation with binary simulation. With the Kirin framework, you can:
- Dynamic intervention binary execution flow
- Dynamic patching of binaries during execution
- Code injection of binaries during execution
- Execute binaries locally instead of running the entire file
- Any patch "shelling" has been shelled program content
Kirin framework can simulate:
- Windows x86 32 / 64 bit
- Linux x86 32 / 64 bit, arm, aarch64, MIPS
- Mac OS x86 32 / 64 bit
- FreeBSD x86 32 / 64 bit
Kirin framework can run on Linux / MacOS / FreeBSD / windows (WSL) and other operating systems, and is not limited by CPU architecture
Demonstration environment
- Hardware: x86 64 bit
- OS: Ubuntu 18.04 64 bit
Demonstrate how to obtain the breaker switch address of wannacry
Kirin framework runs wannacry malware to obtain the switch address of the circuit breaker
Code sample
from qiling import *
def stopatkillerswtich(ql):
ql.uc.emu_stop()
if __name__ == "__main__":
ql = Qiling(["rootfs/x86_windows/bin/wannacry.bin"], "rootfs/x86_windows")
ql.hook_address(stopatkillerswtich, 0x40819a)
ql.run()
Execution output
0x1333804: __set_app_type(0x2)
0x13337ce: __p__fmode() = 0x500007ec
0x13337c3: __p__commode() = 0x500007f0
0x132f1e1: _controlfp(0x10000, 0x30000) = 0x8001f
0x132d151: _initterm(0x40b00c, 0x40b010)
0x1333bc0: __getmainargs(0xffffdf9c, 0xffffdf8c, 0xffffdf98, 0x0, 0xffffdf90) = 0
0x132d151: _initterm(0x40b000, 0x40b008)
0x1001e10: GetStartupInfo(0xffffdfa0)
0x104d9f3: GetModuleHandleA(0x00) = 400000
0x125b18e: InternetOpenA(0x0, 0x1, 0x0, 0x0, 0x0)
0x126f0f1: InternetOpenUrlA(0x0, "http://www.iuqerfsodp9ifjaposdfjhgosurijfaewrwergwea.com", "", 0x0, 0x84000000, 0x0)
from qiling import *
def my_sandbox(path, rootfs):
ql = Qiling(path, rootfs, stdin = sys.stdin, stdout = sys.stdout, stderr = sys.stderr)
# Patch 0x00005930 from br0 to ens33
ql.patch(0x00005930, b'ens33\x00', file_name = b'libChipApi.so')
ql.root = False
ql.run()
if __name__ == "__main__":
my_sandbox(["rootfs/tendaac15/bin/httpd"], "rootfs/tendaac15")
Show me hot fix Windows crackme
The Kirin framework hotfix windows crackme program makes it display the "migration" window.
Code sample
from qiling import *
def force_call_dialog_func(ql):
# get DialogFunc address
lpDialogFunc = ql.unpack32(ql.mem_read(ql.sp - 0x8, 4))
# setup stack memory for DialogFunc
ql.stack_push(0)
ql.stack_push(1001)
ql.stack_push(273)
ql.stack_push(0)
ql.stack_push(0x0401018)
# force EIP to DialogFunc
ql.pc = lpDialogFunc
def my_sandbox(path, rootfs):
ql = Qiling(path, rootfs)
# NOP out some code
ql.patch(0x004010B5, b'\x90\x90')
ql.patch(0x004010CD, b'\x90\x90')
ql.patch(0x0040110B, b'\x90\x90')
ql.patch(0x00401112, b'\x90\x90')
# hook at an address with a callback
ql.hook_address(0x00401016, force_call_dialog_func)
ql.run()
if __name__ == "__main__":
my_sandbox(["rootfs/x86_windows/bin/Easy_CrackMe.exe"], "rootfs/x86_windows")
Execution output
0x10cae10: GetStartupInfo(0xffffdf40)
0x1121fa7: GetStdHandle(0xfffffff6) = 0xfffffff6
0x111fbc4: GetFileType(0xfffffff6) = 0x2
0x1121fa7: GetStdHandle(0xfffffff5) = 0xfffffff5
0x111fbc4: GetFileType(0xfffffff5) = 0x2
0x1121fa7: GetStdHandle(0xfffffff4) = 0xfffffff4
0x111fbc4: GetFileType(0xfffffff4) = 0x2
0x1121fd1: SetHandleCount(0x20) = 32
0x1121fbf: GetCommandLineA() = 0x501091b8
0x111fcd4: GetEnvironmentStringsW() = 0x501091e4
0x1117ffa: WideCharToMultiByte(0x0, 0x0, 0x501091e4, 0x1, 0x0, 0x0, 0x0, 0x0) = 2
0x1117ffa: WideCharToMultiByte(0x0, 0x0, 0x501091e4, 0x1, 0x50002098, 0x2, 0x0, 0x0) = 1
0x111fcbc: FreeEnvironmentStringsW(0x501091e4) = 1
0x1116a0b: GetACP() = 437
0x1121f8f: GetCPInfo(0x1b5, 0xffffdf44) = 1
0x1121f8f: GetCPInfo(0x1b5, 0xffffdf1c) = 1
0x111e43e: GetStringTypeW(0x1, 0x40541c, 0x1, 0xffffd9d8) = 0
0x10ffc95: GetStringTypeExA(0x0, 0x1, 0x405418, 0x1, 0xffffd9d8) = 0
0x111e39c: LCMapStringW(0x0, 0x100, 0x40541c, 0x1, 0x0, 0x0) = 0
0x1128a50: LCMapStringA(0x0, 0x100, 0x405418, 0x1, 0x0, 0x0) = 0
0x111e39c: LCMapStringW(0x0, 0x100, 0x40541c, 0x1, 0x0, 0x0) = 0
0x1128a50: LCMapStringA(0x0, 0x100, 0x405418, 0x1, 0x0, 0x0) = 0
0x111685a: GetModuleFileNameA(0x0, 0x40856c, 0x104) = 42
0x10cae10: GetStartupInfo(0xffffdfa0)
0x11169f3: GetModuleHandleA(0x00) = 400000
0x104cf42: DialogBoxParamA(0x400000, 0x65, 0x00, 0x401020, 0x00) = 0
Input DlgItemText :
<< enter any string or number here >>
0x1063d14: GetDlgItemTextA(0x00, 0x3e8, 0xffffdef4, 0x64) = 3
0x105ea11: MessageBoxA(0x00, "Congratulation !!", "EasyCrackMe", 0x40) = 2
0x1033ba3: EndDialog(0x00, 0x00) = 1
0x1124d12: ExitProcess(0x01)