qilingframework / qiling

A True Instrumentable Binary Emulation Framework
https://qiling.io
GNU General Public License v2.0
5.11k stars 742 forks source link

ql.run partial execution interferes with emulated standard output #1472

Open wdharri2 opened 4 months ago

wdharri2 commented 4 months ago

Bug Description When using ql.run(count=1) to step through the instructions in the provided assembly code, the expected output "B: Hello folks\n" is not emitted to the console. However, running ql.run() without parameters produces the correct output. The issue appears to be related to the behavior of the ql.run(count=1) function, which may not handle the instruction execution or syscall properly in a stepped execution mode.

Sample Code

ql = Qiling([self.executable], rootfs=self.rootfs_loc,
                    verbose=verbose_level)
    for _ in range(20):
        ql.run(count=1)
.data
/* Test comment */
/* Data segment: define our message string and calculate its length. */
msg:
    .ascii        "B: Hello folks\n"
len = . - msg

.text

/* Our application's entry point. */
.globl _start
_start:
    /* syscall write(int fd, const void *buf, size_t count) */
    mov     x0, #1      /* fd := STDOUT_FILENO */
    mov     x1, #1
    subs    x2, x0, x1
    adds    x2, x0, x1
    ldr     x1, =msg    /* buf := msg */
    ldr     x2, =len    /* count := len */
    mov     w8, #64     /* write is syscall #64 */
    svc     #0          /* invoke syscall */

    /* syscall exit(int status) */
    mov     x0, #0      /* status := 0 */
    mov     w8, #93     /* exit is syscall #93 */
    svc     #0          /* invoke syscall */

Expected behavior On svc #0, "B: Hello folks\n" is expected to be emitted to the console. This only occurs when ql.run() is ran with no parameters. However, when I step through the instructions using ql.run(count=1), the expected output never appears.

Additional context I've attempted to capture the output by piping it to a variable but even that is futile. Is there a way to solve this problem?

elicn commented 3 months ago

ql.runis more suitable for a complete run, as it initializes OS and other components. I believe you should be using ql.emu_start for that. Just use the same begin and end values in the loop, and make sure to set count to 1.