Skip to content

Commit

Permalink
Merge pull request #1233 from qilingframework/dev
Browse files Browse the repository at this point in the history
Get ready for 1.4.4
  • Loading branch information
xwings authored Sep 24, 2022
2 parents fd74c83 + 75aaafd commit d6e7ce3
Show file tree
Hide file tree
Showing 123 changed files with 4,896 additions and 3,350 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ jobs:
cd ../qiling
cd ../examples/rootfs/x86_linux/kernel && unzip -P infected m0hamed_rootkit.ko.zip
cd ../../../../
pip3 install -e .[evm]
pip3 install -e .[evm,RE]
if [ ${{ matrix.os }} == 'ubuntu-18.04' ] and [ ${{ matrix.python-version }} == '3.9' ]; then
docker run -it --rm -v ${GITHUB_WORKSPACE}:/qiling qilingframework/qiling:dev bash -c "cd tests && ./test_onlinux.sh"
Expand Down
4 changes: 2 additions & 2 deletions CREDITS.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
#### CI, Website,Documentations, Logo & Swags

- FOO Kevin (chfl4gs) <chfl4gs_at_qiling_io>
- SU muchen (miraisuu) <suu_at_iling_io>
- SU muchen (miraisuu) <suu_at_qiling_io>


#### Key Contributors (in no particular order)
Expand All @@ -36,6 +36,7 @@
- Mark Jansen (learn-more)
- cq674350529
- bkerler (viperbjk)
- bet4it


#### Contributors (in no particular order)
Expand All @@ -53,7 +54,6 @@
- madprogrammer
- danielmoos
- sigeryang
- bet4it
- nullableVoidPtr


Expand Down
49 changes: 48 additions & 1 deletion ChangeLog
Original file line number Diff line number Diff line change
@@ -1,8 +1,55 @@
This file details the changelog of Qiling Framework.

------------------------------------
[Version 1.4.4]: July XX, 2022
[Version 1.4.4]: September 24th, 2022

New features:
- Add r2 extension (#1172)
- Introduce procfs to Linux OS (#1174)
- Add a tracer for IDAPro's Tenet plugin (#1205)

Improvements:
- Collect a few additional DLLs for x8664 (#1167)
- Use global cwd in thread (#1170)
- Fix QlLinuxThreadManagement.threads to be updated appropriately (#1180)
- Fix Unix socket subsystem (#1181)
- Maintenance PR for security and code quality (#1182 #1195)
- Enable android 32bit test (#1184)
- Fix wrong platform_system for unicornafl (#1185)
- Fix arm thumb mode shellcode emulation (#1187)
- Pump unicorn version to 2.0.0 (#1189)
- Procfs improve & pwndbg compatiblity (#1190)
- Fix example script issues (#1193 #1194)
- Introduce a human-friendly disassembler (#1196)
- Fix gdb step/continue handling (#1200)
- Fix README.md (#1203)
- Fix typo of default ip 127.0.0.1 (#1205)
- Temporarily mask Python versions that are not supported by the EVM module (#1208)
- Windows Maintenance PR (#1210)
- Improvements around POSIX sockets (#1216)
- Add x86_64 debug support for Qdb (#1218)
- Renew code for picohttpd (#1221)
- Fix missing retaddr_on_stack in Qdb for arm (#1225)
- Qdb improvments: Mark, Jump and modify register value in qdb (#1226)
- Allow user to build config from dictionary other than disk file (#1227)
- fix(ida): replace __getattribute__ with __getattr__ (#1231)

Contributors:
- jasperla
- bet4it
- chinggg
- elicn
- vhertz
- cgfandia-tii
- wtdcode
- ucgJhe
- aquynh
- kabeor
- oscardagrach
- hamarituc
- EtchProject
- HackingFrogWithSunglasses
- xwings

------------------------------------
[Version 1.4.3]: June 1st, 2022
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ With qltool, easy execution can be performed:
With shellcode:

```
$ ./qltool shellcode --os linux --arch arm --hex -f examples/shellcodes/linarm32_tcp_reverse_shell.hex
$ ./qltool code --os linux --arch arm --format hex -f examples/shellcodes/linarm32_tcp_reverse_shell.hex
```

With binary file:
Expand Down
2 changes: 1 addition & 1 deletion examples/crackme_x86_windows.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
class Solver:
def __init__(self, invalid: bytes):
# create a silent qiling instance
self.ql = Qiling([rf"{ROOTFS}/bin/crackme.exe"], ROOTFS, verbose=QL_VERBOSE.OFF)
self.ql = Qiling([rf"{ROOTFS}/bin/crackme.exe"], ROOTFS, verbose=QL_VERBOSE.DISABLED)

self.ql.os.stdin = pipe.SimpleInStream(sys.stdin.fileno()) # take over the input to the program using a fake stdin
self.ql.os.stdout = pipe.NullOutStream(sys.stdout.fileno()) # disregard program output
Expand Down
12 changes: 11 additions & 1 deletion examples/crackme_x86_windows_setcallback.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,26 +9,36 @@
from qiling import Qiling

def force_call_dialog_func(ql: Qiling):
# this hook is invoked after returning from DialogBoxParamA, so its
# stack frame content is still available to us.

# get DialogFunc address
lpDialogFunc = ql.unpack32(ql.mem.read(ql.arch.regs.esp - 0x8, 4))
lpDialogFunc = ql.stack_read(-8)

# setup stack 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.arch.regs.eip = lpDialogFunc

def my_sandbox(path, rootfs):
ql = Qiling(path, rootfs)

# patch the input validation code: overwrite all its breaking points
# denoted with "jne 0x401135", so it would keep going even if there
# is an error
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 the instruction after returning from DialogBoxParamA
ql.hook_address(force_call_dialog_func, 0x00401016)

ql.run()

if __name__ == "__main__":
Expand Down
9 changes: 8 additions & 1 deletion examples/crackme_x86_windows_unpatch.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,28 @@
from qiling import Qiling

def force_call_dialog_func(ql: Qiling):
# this hook is invoked after returning from DialogBoxParamA, so its
# stack frame content is still available to us.

# get DialogFunc address
lpDialogFunc = ql.unpack32(ql.mem.read(ql.arch.regs.esp - 0x8, 4))
lpDialogFunc = ql.stack_read(-8)

# setup stack 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.arch.regs.eip = lpDialogFunc

def our_sandbox(path, rootfs):
ql = Qiling(path, rootfs)

# hook the instruction after returning from DialogBoxParamA
ql.hook_address(force_call_dialog_func, 0x00401016)

ql.run()

if __name__ == "__main__":
Expand Down
50 changes: 50 additions & 0 deletions examples/extensions/r2/hello_r2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#!/usr/bin/env python3
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#

import sys
sys.path.append('..')

from qiling import Qiling
from qiling.const import QL_VERBOSE
from qiling.extensions.r2 import R2


def func(ql: Qiling, *args, **kwargs):
ql.os.stdout.write(b"=====hooked main=====!\n")
return

def my_sandbox(path, rootfs):
ql = Qiling(path, rootfs, verbose=QL_VERBOSE.DISASM)
# QL_VERBOSE.DISASM will be monkey-patched when r2 is available
r2 = R2(ql)

# search bytes sequence using ql.mem.search
addrs = ql.mem.search(b'llo worl') # return all matching results
print(r2.at(addrs[0])) # find corresponding flag at the address and the offset to the flag
# search string using r2
addr = r2.strings['Hello world!'].vaddr # key must be exactly same
print(addrs[0], addr)
# print xref to string "Hello world!"
print(r2.refto(addr))
# write to string using ql.mem.write
ql.mem.write(addr, b"No hello, Bye!\x00")

# get function address and hook it
ql.hook_address(func, r2.functions['main'].offset)
# enable trace powered by r2 symsmap
# r2.enable_trace()
ql.run()

if __name__ == "__main__":
my_sandbox(["rootfs/x86_windows/bin/x86_hello.exe"], "rootfs/x86_windows")

# test shellcode mode
ARM64_LIN = bytes.fromhex('420002ca210080d2400080d2c81880d2010000d4e60300aa01020010020280d2681980d2010000d4410080d2420002cae00306aa080380d2010000d4210400f165ffff54e0000010420002ca210001caa81b80d2010000d4020004d27f0000012f62696e2f736800')
print("\nLinux ARM 64bit Shellcode")
ql = Qiling(code=ARM64_LIN, archtype="arm64", ostype="linux", verbose=QL_VERBOSE.DEBUG)
r2 = R2(ql)
# disassemble 32 instructions
print(r2._cmd('pd 32'))
ql.run()
5 changes: 4 additions & 1 deletion examples/hello_arm_qnx_customapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,26 @@
sys.path.append("..")

from qiling import Qiling
from qiling.const import QL_INTERCEPT, QL_CALL_BLOCK, QL_VERBOSE
from qiling.const import QL_INTERCEPT, QL_CALL_BLOCK
from qiling.os.const import STRING

def my_puts_onenter(ql: Qiling):
params = ql.os.resolve_fcall_params({'s': STRING})

print(f'puts("{params["s"]}")')

return QL_CALL_BLOCK

def my_printf_onenter(ql: Qiling):
params = ql.os.resolve_fcall_params({'s': STRING})

print(f'printf("{params["s"]}")')

return QL_CALL_BLOCK

def my_puts_onexit(ql: Qiling):
print(f'after puts')

return QL_CALL_BLOCK

if __name__ == "__main__":
Expand Down
12 changes: 8 additions & 4 deletions examples/hello_arm_uboot.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,12 @@
from qiling.os.const import STRING

def get_kaimendaji_password():
def my_getenv(ql, *args, **kwargs):
env = {"ID": b"000000000000000", "ethaddr": b"11:22:33:44:55:66"}
def my_getenv(ql: Qiling):
env = {
"ID" : b"000000000000000",
"ethaddr" : b"11:22:33:44:55:66"
}

params = ql.os.resolve_fcall_params({'key': STRING})
value = env.get(params["key"], b"")

Expand All @@ -22,7 +26,7 @@ def my_getenv(ql, *args, **kwargs):
ql.arch.regs.r0 = value_addr
ql.arch.regs.arch_pc = ql.arch.regs.lr

def get_password(ql, *args, **kwargs):
def get_password(ql: Qiling):
password_raw = ql.mem.read(ql.arch.regs.r0, ql.arch.regs.r2)

password = ''
Expand All @@ -34,7 +38,7 @@ def get_password(ql, *args, **kwargs):

print("The password is: %s" % password)

def partial_run_init(ql):
def partial_run_init(ql: Qiling):
# argv prepare
ql.arch.regs.arch_sp -= 0x30
arg0_ptr = ql.arch.regs.arch_sp
Expand Down
17 changes: 10 additions & 7 deletions examples/hello_linuxx8664_intercept.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,24 @@
sys.path.append("..")

from qiling import Qiling
from qiling.const import QL_INTERCEPT, QL_VERBOSE
from qiling.const import QL_INTERCEPT
from qiling.os.linux.syscall_nums import SYSCALL_NR

def write_onenter(ql: Qiling, arg1, arg2, arg3, *args):
def write_onenter(ql: Qiling, fd: int, buf: int, count: int):
print("enter write syscall!")
ql.arch.regs.rsi = arg2 + 1
ql.arch.regs.rdx = arg3 - 1

def write_onexit(ql: Qiling, arg1, arg2, arg3, *args):
ql.arch.regs.rsi = buf + 1
ql.arch.regs.rdx = count - 1

def write_onexit(ql: Qiling, fd: int, buf: int, count: int, retval: int):
print("exit write syscall!")
ql.arch.regs.rax = arg3 + 1

ql.arch.regs.rax = count + 1

if __name__ == "__main__":
ql = Qiling(["rootfs/x8664_linux/bin/x8664_hello"], "rootfs/x8664_linux", verbose=QL_VERBOSE.DEBUG)
ql = Qiling(["rootfs/x8664_linux/bin/x8664_hello"], "rootfs/x8664_linux")

ql.os.set_syscall(SYSCALL_NR.write, write_onenter, QL_INTERCEPT.ENTER)
ql.os.set_syscall(SYSCALL_NR.write, write_onexit, QL_INTERCEPT.EXIT)

ql.run()
15 changes: 11 additions & 4 deletions examples/hello_x8664_linux_part_exec.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,20 @@
from qiling.const import QL_VERBOSE

if __name__ == "__main__":
ql = Qiling(["rootfs/x8664_linux/bin/sleep_hello"], "rootfs/x8664_linux", verbose=QL_VERBOSE.DEFAULT)
def dump(ql, *args, **kw):
ql.save(reg=False, cpu_context=True, snapshot="/tmp/snapshot.bin")
ql.emu_stop()

# load base address from profile file
ql = Qiling(["rootfs/x8664_linux/bin/sleep_hello"], "rootfs/x8664_linux", verbose=QL_VERBOSE.DEBUG)
X64BASE = int(ql.profile.get("OS64", "load_address"), 16)
ql.hook_address(dump, X64BASE + 0x1094)
ql.run()

ql = Qiling(["rootfs/x8664_linux/bin/sleep_hello"], "rootfs/x8664_linux", verbose=QL_VERBOSE.DISASM)
# load base address from profile file
X64BASE = int(ql.profile.get("OS64", "load_address"), 16)
ql.restore(snapshot="/tmp/snapshot.bin")
# set execution starting and ending points
begin_point = X64BASE + 0x109e
end_point = X64BASE + 0x10bc

ql.run(begin=begin_point, end=end_point)
ql.run(begin = begin_point, end = end_point)
2 changes: 1 addition & 1 deletion examples/rootfs
14 changes: 7 additions & 7 deletions examples/sality.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,16 +119,16 @@ def hook_WriteFile(ql: Qiling, address: int, params):
if hFile == 0x13371337:
buffer = ql.mem.read(lpBuffer, nNumberOfBytesToWrite)
try:
r, nNumberOfBytesToWrite = utils.io_Write(ql.amsint32_driver, buffer)
nNumberOfBytesToWrite = utils.io_Write(ql.amsint32_driver, buffer)
ql.mem.write_ptr(lpNumberOfBytesWritten, nNumberOfBytesToWrite, 4)
except Exception as e:
except Exception:
ql.log.exception("")
print("Exception = %s" % str(e))
r = 1
if r:
return 1
r = False
else:
return 0
r = True

return int(r)

else:
return _WriteFile(ql, address, params)

Expand Down
Loading

0 comments on commit d6e7ce3

Please sign in to comment.