Skip to content

Commit cc8b111

Browse files
committed
Merge branch 'dev' of github.com:qilingframework/qiling into dev
2 parents 9ade532 + 77fa982 commit cc8b111

File tree

18 files changed

+272
-99
lines changed

18 files changed

+272
-99
lines changed

ChangeLog

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,10 @@ BREAK CHANGE
1111
------------------------------------
1212
[Version 1.2.1]: December [SOMETHING], 2020
1313

14+
- Added support for custom envs variables inside IDA plugin
1415
- Demigod: Fixed lkm mapping and added support for MIPS32EL
1516
- Demigod: Added support for Linux x86 32bit
17+
- Added support from binaries that return from their entrypoint (PE / ELF). Configure Qiling with 'stop_on_stackpointer' or 'stop_on_exit_trap'.
1618

1719

1820
------------------------------------
4.83 KB
Binary file not shown.
1.5 KB
Binary file not shown.
4.61 KB
Binary file not shown.
1 KB
Binary file not shown.

examples/src/windows/return_main.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/*
2+
Build with tcc (https://download.savannah.gnu.org/releases/tinycc/)
3+
Renamed 64 bit tcc to 'tcc64' for convenience:
4+
5+
tcc return_main.c -nostdlib -o return_main32.exe
6+
tcc64 return_main.c -nostdlib -o return_main64.exe
7+
*/
8+
9+
int _start()
10+
{
11+
return 0;
12+
}

qiling/core.py

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ def __init__(
4444
append=None,
4545
libcache = False,
4646
multithread = False,
47+
stop_on_stackpointer = False,
48+
stop_on_exit_trap = False,
4749
stdin=0,
4850
stdout=0,
4951
stderr=0,
@@ -77,6 +79,7 @@ def __init__(
7779
self._platform = ostype_convert(platform.system().lower())
7880
self._internal_exception = None
7981
self._uc = None
82+
self._stop_options = QlStopOptions(stackpointer=stop_on_stackpointer, exit_trap=stop_on_exit_trap)
8083

8184
##################################
8285
# Definition after ql=Qiling() #
@@ -200,6 +203,9 @@ def __init__(
200203
# Setup Outpt
201204
self.os.setup_output()
202205

206+
# Add extra guard options when configured to do so
207+
self._init_stop_guard()
208+
203209

204210
#####################
205211
# Qiling Components #
@@ -659,6 +665,18 @@ def uc(self):
659665
def uc(self, u):
660666
self._uc = u
661667

668+
@property
669+
def stop_options(self) -> "QlStopOptions":
670+
""" The stop options configured:
671+
- stackpointer: Stop execution on a negative stackpointer
672+
- exit_trap: Stop execution when the ip enters a guarded region
673+
- any: Is any of the options enabled?
674+
675+
Returns:
676+
QlStopOptions: What stop options are configured
677+
"""
678+
return self._stop_options
679+
662680
def __enable_bin_patch(self):
663681
for addr, code in self.patch_bin:
664682
self.mem.write(self.loader.load_address + addr, code)
@@ -670,7 +688,46 @@ def enable_lib_patch(self):
670688
self.mem.write(self.mem.get_lib_base(filename) + addr, code)
671689
except:
672690
raise RuntimeError("Fail to patch %s at address 0x%x" % (filename, addr))
673-
691+
692+
def _init_stop_guard(self):
693+
if not self.stop_options.any:
694+
return
695+
696+
# Allocate a guard page, we need this in both cases
697+
# On a negative stack pointer, we still need a return address (otherwise we end up at 0)
698+
# Make sure it is not close to the heap (PE), otherwise the heap cannot grow
699+
self._exit_trap_addr = self.mem.find_free_space(0x1000, min_addr=0x9000000, alignment=0x10)
700+
self.mem.map(self._exit_trap_addr, 0x1000, info='[Stop guard]')
701+
702+
# Stop on a negative stack pointer
703+
if self.stop_options.stackpointer:
704+
def _check_sp(ql, address, size):
705+
if not ql.loader.skip_exit_check:
706+
sp = ql._initial_sp - ql.reg.arch_sp
707+
if sp < 0:
708+
logging.info('Process returned from entrypoint (stackpointer)!')
709+
ql.emu_stop()
710+
711+
self.hook_code(_check_sp)
712+
713+
# Stop when running to exit trap address
714+
if self.stop_options.exit_trap:
715+
def _exit_trap(ql):
716+
logging.info('Process returned from entrypoint (exit_trap)!')
717+
ql.emu_stop()
718+
719+
self.hook_address(_exit_trap, self._exit_trap_addr)
720+
721+
def write_exit_trap(self):
722+
self._initial_sp = self.reg.arch_sp
723+
if self.stop_options.any:
724+
if not self.loader.skip_exit_check:
725+
logging.debug(f'Setting up exit trap at 0x{hex(self._exit_trap_addr)}')
726+
self.stack_write(0, self._exit_trap_addr)
727+
elif self.stop_options.exit_trap:
728+
logging.debug(f'Loader {self.loader} requested to skip exit_trap!')
729+
730+
674731
###############
675732
# Qiling APIS #
676733
###############
@@ -683,6 +740,7 @@ def run(self, begin=None, end=None, timeout=0, count=0):
683740
self.exit_point = end
684741
self.timeout = timeout
685742
self.count = count
743+
self.write_exit_trap()
686744

687745
# init debugger
688746
if self._debugger != False and self._debugger != None:

0 commit comments

Comments
 (0)