fix documents and minor changes

This commit is contained in:
xwings
2026-07-02 08:54:12 +08:00
107 changed files with 6195 additions and 1154 deletions
+4
View File
@@ -0,0 +1,4 @@
[CODE]
load_address = 0x10000000
entry_point = 0x10000008
ram_size = 0xa00000
@@ -5,7 +5,7 @@
# Everything about the bug and firmware https://www.exploit-db.com/exploits/33863
import os,sys
import sys
sys.path.append("../../..")
from qiling import Qiling
@@ -13,7 +13,7 @@ from qiling.const import QL_VERBOSE
from qiling.extensions.afl import ql_afl_fuzz
def main(input_file, enable_trace=False):
def main(input_file: str):
env_vars = {
"REQUEST_METHOD": "POST",
@@ -24,40 +24,36 @@ def main(input_file, enable_trace=False):
# "CONTENT_LENGTH": "8", # no needed
}
ql = Qiling(["./rootfs/htdocs/web/hedwig.cgi"], "./rootfs",
verbose=QL_VERBOSE.DEBUG, env=env_vars, console=enable_trace)
ql = Qiling(["./rootfs/htdocs/web/hedwig.cgi"], "./rootfs", verbose=QL_VERBOSE.DISABLED, env=env_vars)
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 place_input_callback(ql: Qiling, data: bytes, _: int) -> bool:
# construct the payload
payload = b''.join((b"HTTP_COOKIE=uid=1234&password=", bytes(data), b"\x00", ql_path, b"\x00"))
# patch the value of 'HTTP_COOKIE' in memory
ql.mem.write(target_addr, payload)
# payload is in place, we are good to go
return True
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]
addr = ql.mem.search(b"HTTP_COOKIE=uid=1234&password=")
target_addr = addr[0]
ql_path = ql.path.encode()
main_addr = ql.loader.elf_entry
ql.hook_address(callback=start_afl, address=main_addr)
ql.hook_address(start_afl, ql.loader.elf_entry)
try:
ql.run()
os._exit(0)
except:
if enable_trace:
print("\nFuzzer Went Shit")
os._exit(0)
ql.run()
if __name__ == "__main__":
if len(sys.argv) == 1:
if len(sys.argv) < 2:
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])
main(sys.argv[1])
+101
View File
@@ -0,0 +1,101 @@
##############################################################################
# This example is meant to demonstrate the modifications necessary
# to enable code coverage when emulating small code snippets or bare-metal
# code.
##############################################################################
from qiling import Qiling
from qiling.const import QL_ARCH, QL_OS, QL_VERBOSE
from qiling.extensions.coverage import utils as cov_utils
from qiling.loader.loader import Image
import os
BASE_ADDRESS = 0x10000000
CHECKSUM_FUNC_ADDR = BASE_ADDRESS + 0x8
END_ADDRESS = 0x100000ba
DATA_ADDR = 0xa0000000 # Arbitrary address for data
STACK_ADDR = 0xb0000000 # Arbitrary address for stack
# Python implementation of the checksum function being emulated
# This checksum function is intended to have different code paths based on the input
# which is useful for observing code coverage
def checksum_function(input_data_buffer: bytes):
expected_checksum_python = 0
input_data_len = len(input_data_buffer)
if input_data_len >= 1 and input_data_buffer[0] == 0xDE: # MAGIC_VALUE_1
for i in range(min(input_data_len, 4)):
expected_checksum_python += input_data_buffer[i]
expected_checksum_python += 0x10
elif input_data_len >= 2 and input_data_buffer[1] == 0xAD: # MAGIC_VALUE_2
for i in range(input_data_len):
expected_checksum_python ^= input_data_buffer[i]
expected_checksum_python += 0x20
else:
for i in range(input_data_len):
expected_checksum_python += input_data_buffer[i]
expected_checksum_python &= 0xFF # Ensure it's a single byte
return expected_checksum_python
def unmapped_handler(ql: Qiling, type: int, addr: int, size: int, value: int) -> None:
print(f"Unmapped Memory R/W, trying to access {size:d} bytes at {addr:#010x} from {ql.arch.regs.pc:#010x}")
def emulate_checksum_function(input_data_buffer: bytes) -> None:
print(f"\n--- Testing with input: {input_data_buffer.hex()} ---")
test_file = "rootfs/blob/example_raw.bin"
with open(test_file, "rb") as f:
raw_code: bytes = f.read()
ql: Qiling = Qiling(
code=raw_code,
archtype=QL_ARCH.ARM,
ostype=QL_OS.BLOB,
profile="blob_raw.ql",
verbose=QL_VERBOSE.DEBUG,
thumb=True
)
''' monkeypatch - Correcting the loader image name, used for coverage collection
removing all images with name 'blob_code' that were created by the blob loader.
This is necessary because some code coverage visualization tools require the
module name to match that of the input file '''
ql.loader.images = [img for img in ql.loader.images if img.path != 'blob_code']
ql.loader.images.append(Image(ql.loader.load_address, ql.loader.load_address + ql.os.code_ram_size, os.path.basename(test_file)))
input_data_len: int = len(input_data_buffer)
# Map memory for the data and stack
ql.mem.map(STACK_ADDR, 0x2000)
ql.mem.map(DATA_ADDR, ql.mem.align_up(input_data_len + 0x100)) # Map enough space for data
# Write input data
ql.mem.write(DATA_ADDR, input_data_buffer)
# Set up the stack pointer
ql.arch.regs.sp = STACK_ADDR + 0x2000 - 4
# Set up argument registers
ql.arch.regs.r0 = DATA_ADDR
ql.arch.regs.r1 = input_data_len
# Set the program counter to the function's entry point
ql.arch.regs.pc = CHECKSUM_FUNC_ADDR
# Set the return address (LR) to a dummy address.
ql.arch.regs.lr = 0xbebebebe
ql.hook_mem_unmapped(unmapped_handler)
#ql.debugger="gdb:127.0.0.1:9999"
# Start emulation
print(f"Starting emulation at PC: {hex(ql.arch.regs.pc)}")
try:
with cov_utils.collect_coverage(ql, 'drcov', 'output.cov'):
ql.run(begin=CHECKSUM_FUNC_ADDR, end=END_ADDRESS)
except Exception as e:
print(f"Emulation error: {e}")
print(f"Emulated checksum: {hex(ql.arch.regs.r0)}")
if __name__ == "__main__":
data = b"\x01\x02\x03\x04\x05" # Example input data
emulate_checksum_function(data)
+59 -45
View File
@@ -8,68 +8,82 @@ sys.path.append("..")
from qiling.core import Qiling
from qiling.const import QL_ARCH, QL_OS, QL_VERBOSE
from qiling.os.const import STRING
from qiling.os.const import STRING, SIZE_T, POINTER
def get_kaimendaji_password():
def my_getenv(ql: Qiling):
env = {
"ID" : b"000000000000000",
"ethaddr" : b"11:22:33:44:55:66"
}
def my_getenv(ql: Qiling):
env = {
"ID" : b"000000000000000",
"ethaddr" : b"11:22:33:44:55:66"
}
params = ql.os.resolve_fcall_params({'key': STRING})
value = env.get(params["key"], b"")
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)
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
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)
def get_password(ql: Qiling):
# we land on a memcmp call, where the real password is being compared to
# the one provided by the user. we can follow the arguments to read the
# real password
print("The password is: %s" % password)
params = ql.os.resolve_fcall_params({
'ptr1': POINTER, # points to real password
'ptr2': POINTER, # points to user provided password
'size': SIZE_T # comparison length
})
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")
ptr1 = params['ptr1']
size = params['size']
ql.arch.regs.arch_sp -= 0x10
arg1_ptr = ql.arch.regs.arch_sp
ql.mem.write(arg1_ptr, b"000000") # arbitrary password
password_raw = ql.mem.read(ptr1, size)
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)
def __hex_digit(ch: int) -> str:
off = ord('0') if ch in range(10) else ord('a') - 10
ql.arch.regs.r2 = 2
ql.arch.regs.r3 = argv_ptr
return chr(ch + off)
with open("../examples/rootfs/blob/u-boot.bin.img", "rb") as f:
uboot_code = f.read()
# should be: "013f1f"
password = "".join(__hex_digit(ch) for ch in password_raw)
ql = Qiling(code=uboot_code[0x40:], archtype=QL_ARCH.ARM, ostype=QL_OS.BLOB, profile="uboot_bin.ql", verbose=QL_VERBOSE.OFF)
print(f'The password is: {password}')
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)
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.run(image_base_addr + 0x486B4, image_base_addr + 0x48718)
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
if __name__ == "__main__":
get_kaimendaji_password()
with open("../examples/rootfs/blob/u-boot.bin.img", "rb") as f:
uboot_code = f.read()
ql = Qiling(code=uboot_code[0x40:], archtype=QL_ARCH.ARM, ostype=QL_OS.BLOB, profile="uboot_bin.ql", verbose=QL_VERBOSE.DEBUG)
imgbase = ql.loader.images[0].base
ql.hook_address(my_getenv, imgbase + 0x13AC0)
ql.hook_address(get_password, imgbase + 0x48634)
partial_run_init(ql)
ql.run(imgbase + 0x486B4, imgbase + 0x48718)
+1 -1
View File
@@ -159,7 +159,7 @@ def hook_StartServiceA(ql: Qiling, address: int, params):
init_unseen_symbols(ql.amsint32_driver, ntoskrnl.base+0xb7695, b"NtTerminateProcess", 0, "ntoskrnl.exe")
#ql.amsint32_driver.debugger= ":9999"
try:
ql.amsint32_driver.load()
ql.amsint32_driver.run()
return 1
except UcError as e:
print("Load driver error: ", e)
+8
View File
@@ -80,6 +80,7 @@ CALL :collect_dll32 setupapi.dll
CALL :collect_dll32 shell32.dll
CALL :collect_dll32 shlwapi.dll
CALL :collect_dll32 sspicli.dll
CALL :collect_dll32 symcryptk.dll
CALL :collect_dll32 ucrtbase.dll
CALL :collect_dll32 ucrtbased.dll
CALL :collect_dll32 urlmon.dll
@@ -94,6 +95,9 @@ CALL :collect_dll32 wininet.dll
CALL :collect_dll32 winmm.dll
CALL :collect_dll32 ws2_32.dll
CALL :collect_dll32 wsock32.dll
CALL :collect_dll32 msvcp140.dll
CALL :collect_dll32 msvcp140_1.dll
CALL :collect_dll32 msvcp140_2.dll
CALL :collect_dll32 downlevel\api-ms-win-core-fibers-l1-1-1.dll
CALL :collect_dll32 downlevel\api-ms-win-core-localization-l1-2-1.dll
@@ -122,6 +126,7 @@ CALL :collect_dll64 rpcrt4.dll
CALL :collect_dll64 sechost.dll
CALL :collect_dll64 shell32.dll
CALL :collect_dll64 shlwapi.dll
CALL :collect_dll64 symcryptk.dll
CALL :collect_dll64 user32.dll
CALL :collect_dll64 vcruntime140.dll
CALL :collect_dll64 vcruntime140d.dll
@@ -131,6 +136,9 @@ CALL :collect_dll64 win32u.dll
CALL :collect_dll64 winhttp.dll
CALL :collect_dll64 wininet.dll
CALL :collect_dll64 ws2_32.dll
CALL :collect_dll64 msvcp140.dll
CALL :collect_dll64 msvcp140_1.dll
CALL :collect_dll64 msvcp140_2.dll
CALL :collect_dll64 downlevel\api-ms-win-crt-heap-l1-1-0.dll
CALL :collect_dll64 downlevel\api-ms-win-crt-locale-l1-1-0.dll
+52
View File
@@ -0,0 +1,52 @@
# Makefile for Bare-Metal ARM Checksum Calculator
# --- Toolchain Definitions ---
TOOLCHAIN_PREFIX = arm-none-eabi
# Compiler, Linker, and Objcopy executables
CC = $(TOOLCHAIN_PREFIX)-gcc
LD = $(TOOLCHAIN_PREFIX)-gcc
OBJCOPY = $(TOOLCHAIN_PREFIX)-objcopy
# --- Source and Output Files ---
SRCS = example_raw.c
OBJS = $(SRCS:.c=.o) # Convert .c to .o
ELF = example_raw.elf
BIN = example_raw.bin
# --- Linker Script ---
LDSCRIPT = linker.ld
# --- Compiler Flags ---
CFLAGS = -c -O0 -mcpu=cortex-a7 -mthumb -ffreestanding -nostdlib
# --- Linker Flags ---
LDFLAGS = -T $(LDSCRIPT) -nostdlib
# --- Objcopy Flags ---
OBJCOPYFLAGS = -O binary
# --- Default Target ---
.PHONY: all clean
all: $(BIN)
# Rule to build the raw binary (.bin) from the ELF file
$(BIN): $(ELF)
$(OBJCOPY) $(OBJCOPYFLAGS) $< $@
@echo "Successfully created $(BIN)"
# Rule to link the object file into an ELF executable
$(ELF): $(OBJS) $(LDSCRIPT)
$(LD) $(LDFLAGS) $(OBJS) -o $@
@echo "Successfully linked $(ELF)"
# Rule to compile the C source file into an object file
%.o: %.c
$(CC) $(CFLAGS) $< -o $@
@echo "Successfully compiled $<"
# --- Clean Rule ---
clean:
rm -f $(OBJS) $(ELF) $(BIN)
@echo "Cleaned build artifacts."
+56
View File
@@ -0,0 +1,56 @@
// example checksum algorithm to demonstrate raw binary code coverage in qiling
// example_raw.c
// Define some magic values
#define MAGIC_VALUE_1 0xDE
#define MAGIC_VALUE_2 0xAD
// This function calculates a checksum with branches based on input data
// It takes a pointer to data and its length
// Returns the checksum (unsigned char to fit in a byte)
unsigned char calculate_checksum(const unsigned char *data, unsigned int length) {
unsigned char checksum = 0;
// Branch 1: Check for MAGIC_VALUE_1 at the start
if (length >= 1 && data[0] == MAGIC_VALUE_1) {
// If first byte is MAGIC_VALUE_1, do a simple sum of first 4 bytes
// (or up to length if less than 4)
for (unsigned int i = 0; i < length && i < 4; i++) {
checksum += data[i];
}
// Add a fixed offset to make this path distinct
checksum += 0x10;
}
// Branch 2: Check for MAGIC_VALUE_2 at the second byte
else if (length >= 2 && data[1] == MAGIC_VALUE_2) {
// If second byte is MAGIC_VALUE_2, do a XOR sum of all bytes
for (unsigned int i = 0; i < length; i++) {
checksum ^= data[i];
}
// Add a fixed offset to make this path distinct
checksum += 0x20;
}
// Default Branch: Standard byte sum checksum
else {
for (unsigned int i = 0; i < length; i++) {
checksum += data[i];
}
}
return checksum;
}
// Minimal entry point for bare-metal.
// This function will not be called directly during Qiling emulation,
// but it's needed for the linker to have an entry point.
__attribute__((section(".text.startup")))
void _start() {
// In a real bare-metal application, this would initialize hardware,
// set up stacks, etc. For this example, it's just a placeholder.
// We'll call calculate_checksum directly from our Qiling script.
while (1) {
// Do nothing, or perhaps put the CPU to sleep
asm volatile ("wfi"); // Wait For Interrupt (ARM instruction)
}
}
+39
View File
@@ -0,0 +1,39 @@
/* linker.ld */
ENTRY(_start) /* Define the entry point of our program */
/* Define memory regions - simple RAM region for this example */
MEMORY
{
ram (rwx) : ORIGIN = 0x10000000, LENGTH = 64K /* 64KB of RAM for our program */
}
SECTIONS
{
/* Define the start of our program in memory.
*/
. = 0x10000000;
.text : {
KEEP(*(.text.startup)) /* Keep the _start function */
*(.text) /* All other code */
*(.text.*)
*(.rodata) /* Read-only data */
*(.rodata.*)
. = ALIGN(4);
} > ram /* Place .text section in the 'ram' region */
.data : {
. = ALIGN(4);
*(.data) /* Initialized data */
*(.data.*)
. = ALIGN(4);
} > ram
.bss : {
. = ALIGN(4);
*(.bss)
*(.bss.*)
. = ALIGN(4);
} > ram
}
+4
View File
@@ -33,6 +33,7 @@ TARGETS = \
x8664_hello_cpp \
x8664_hello_cpp_static \
x8664_cloexec_test \
x8664_linux_onestraw \
patch_test.bin
.PHONY: all clean
@@ -124,7 +125,10 @@ libpatch_test.so: patch_test.so.h patch_test.so.c
$(CC) $(CPPFLAGS) -Wall -s -O0 -shared -fpic -o $@ patch_test.so.c
patch_test.bin: patch_test.bin.c libpatch_test.so
$(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $^
x8664_onestraw_server: x8664_linux_onestraw.c
$(CC) $(CPPFLAGS) $(CFLAGS) -m64 -o $@ $<
$(OBJS):%.o:%.c
$(CC) $(CFLAGS) -c $< -o $@
+54
View File
@@ -0,0 +1,54 @@
#define MAX_EVENTS 5
#define READ_SIZE 10
#include <stdio.h> // for fprintf()
#include <unistd.h> // for close(), read()
#include <sys/epoll.h> // for epoll_create1(), epoll_ctl(), struct epoll_event
#include <string.h> // for strncmp
int main()
{
//setvbuf(stdin, NULL, _IONBF, 0);
int running = 1, event_count, i;
size_t bytes_read;
char read_buffer[READ_SIZE + 1];
struct epoll_event event, events[MAX_EVENTS];
int epoll_fd = epoll_create1(0);
if (epoll_fd == -1) {
fprintf(stderr, "Failed to create epoll file descriptor\n");
return 1;
}
event.events = EPOLLIN;
event.data.fd = 0;
if(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, 0, &event))
{
fprintf(stderr, "Failed to add file descriptor to epoll\n");
close(epoll_fd);
return 1;
}
while (running) {
printf("\nPolling for input...\n");
event_count = epoll_wait(epoll_fd, events, MAX_EVENTS, 30000);
printf("%d ready events\n", event_count);
for (i = 0; i < event_count; i++) {
printf("Reading file descriptor '%d' -- ", events[i].data.fd);
bytes_read = read(events[i].data.fd, read_buffer, READ_SIZE);
printf("%zd bytes read.\n", bytes_read);
read_buffer[bytes_read] = '\0';
printf("Read '%s'\n", read_buffer);
if(!strncmp(read_buffer, "stop\n", 5))
running = 0;
}
}
if (close(epoll_fd)) {
fprintf(stderr, "Failed to close epoll file descriptor\n");
return 1;
}
return 0;
}
+199
View File
@@ -0,0 +1,199 @@
/*
* Attention:
* To keep things simple, do not handle socket/bind/listen/.../epoll_create/epoll_wait API error
*/
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/epoll.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#define DEFAULT_PORT 8000
#define MAX_CONN 16
#define MAX_EVENTS 32
#define BUF_SIZE 16
#define MAX_LINE 256
void server_run();
void client_run();
int main(int argc, char *argv[])
{
int opt;
char role = 's';
while ((opt = getopt(argc, argv, "cs")) != -1) {
switch (opt) {
case 'c':
role = 'c';
break;
case 's':
break;
default:
printf("usage: %s [-cs]\n", argv[0]);
exit(1);
}
}
if (role == 's') {
server_run();
} else {
client_run();
}
return 0;
}
/*
* register events of fd to epfd
*/
static void epoll_ctl_add(int epfd, int fd, uint32_t events)
{
struct epoll_event ev;
ev.events = events;
ev.data.fd = fd;
if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) == -1) {
perror("epoll_ctl()\n");
exit(1);
}
}
static void set_sockaddr(struct sockaddr_in *addr)
{
bzero((char *)addr, sizeof(struct sockaddr_in));
addr->sin_family = AF_INET;
addr->sin_addr.s_addr = INADDR_ANY;
addr->sin_port = htons(DEFAULT_PORT);
}
static int setnonblocking(int sockfd)
{
if (fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL, 0) | O_NONBLOCK) ==
-1) {
return -1;
}
return 0;
}
/*
* epoll echo server
*/
void server_run()
{
int i;
int n;
int epfd;
int nfds;
int listen_sock;
int conn_sock;
int socklen;
char buf[BUF_SIZE];
struct sockaddr_in srv_addr;
struct sockaddr_in cli_addr;
struct epoll_event events[MAX_EVENTS];
listen_sock = socket(AF_INET, SOCK_STREAM, 0);
set_sockaddr(&srv_addr);
bind(listen_sock, (struct sockaddr *)&srv_addr, sizeof(srv_addr));
setnonblocking(listen_sock);
listen(listen_sock, MAX_CONN);
epfd = epoll_create(1);
epoll_ctl_add(epfd, listen_sock, EPOLLIN | EPOLLOUT | EPOLLET);
socklen = sizeof(cli_addr);
int a;
for (a = 0; a < 2; a++) {
nfds = epoll_wait(epfd, events, MAX_EVENTS, -1);
for (i = 0; i < nfds; i++) {
if (events[i].data.fd == listen_sock) {
/* handle new connection */
conn_sock =
accept(listen_sock,
(struct sockaddr *)&cli_addr,
&socklen);
inet_ntop(AF_INET, (char *)&(cli_addr.sin_addr),
buf, sizeof(cli_addr));
printf("[+] connected with %s:%d\n", buf,
ntohs(cli_addr.sin_port));
setnonblocking(conn_sock);
epoll_ctl_add(epfd, conn_sock,
EPOLLIN | EPOLLET | EPOLLRDHUP |
EPOLLHUP);
} else if (events[i].events & EPOLLIN) {
/* handle EPOLLIN event */
for (;;) {
bzero(buf, sizeof(buf));
n = read(events[i].data.fd, buf,
sizeof(buf));
if (n <= 0 /* || errno == EAGAIN */ ) {
break;
} else {
printf("[+] data: %s\n", buf);
write(events[i].data.fd, buf,
strlen(buf));
}
}
} else {
printf("[+] unexpected\n");
}
/* check if the connection is closing */
if (events[i].events & (EPOLLRDHUP | EPOLLHUP)) {
printf("[+] connection closed\n");
epoll_ctl(epfd, EPOLL_CTL_DEL,
events[i].data.fd, NULL);
close(events[i].data.fd);
continue;
}
}
}
}
/*
* test clinet
*/
void client_run()
{
int n;
int c;
int sockfd;
char buf[MAX_LINE];
struct sockaddr_in srv_addr;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
set_sockaddr(&srv_addr);
if (connect(sockfd, (struct sockaddr *)&srv_addr, sizeof(srv_addr)) < 0) {
perror("connect()");
exit(1);
}
for (;;) {
printf("input: ");
fgets(buf, sizeof(buf), stdin);
c = strlen(buf) - 1;
buf[c] = '\0';
write(sockfd, buf, c + 1);
bzero(buf, sizeof(buf));
while (errno != EAGAIN
&& (n = read(sockfd, buf, sizeof(buf))) > 0) {
printf("echo: %s\n", buf);
bzero(buf, sizeof(buf));
c -= n;
if (c <= 0) {
break;
}
}
}
close(sockfd);
}
@@ -0,0 +1,11 @@
// This is the default Hello World program generated by Visual Studio 2022.
#include <iostream>
int main()
{
std::cout << "Hello World!\n";
return 0;
}
+3
View File
@@ -0,0 +1,3 @@
In this folder: Sources for programs intended to help test C++ features and software exceptions.
Compile with MSVC (Visual Studio 2022)
+95
View File
@@ -0,0 +1,95 @@
#include <iostream>
#include <cstdlib>
/*
* Test simple try..catch.
*/
void test1()
{
std::cout << "y";
try {
std::cout << "y";
throw (unsigned int)0x12345678;
std::cout << "n";
}
catch(unsigned int n) {
n;
std::cout << "y";
}
std::cout << "y";
}
/*
* Test simple try..catch with throw.
*/
void test2()
{
std::cout << "y";
try {
std::cout << "y";
throw (unsigned int)0x12345679;
std::cout << "n";
}
catch (unsigned int n) {
n;
if (n == 0x12345679) {
std::cout << "y";
}
else {
std::cout << "n";
}
}
std::cout << "y";
}
/*
* Test nested try..catch with throw.
*/
void test3()
{
std::cout << "y";
try {
std::cout << "y";
try {
std::cout << "y";
throw (unsigned int)0x1234567A;
std::cout << "n";
}
catch (unsigned int n) {
n;
if (n == 0x1234567A) {
std::cout << "y";
}
else {
std::cout << "n";
}
}
std::cout << "y";
}
catch (unsigned int n) {
n;
std::cout << "n";
}
std::cout << "y";
}
int main()
{
/*
* For this program, all subtests successful will print:
* - 14 'y'
* - 0 'n'
*/
test1();
test2();
test3();
}
@@ -0,0 +1,46 @@
#include <windows.h>
#include <cstdio>
LONG WINAPI CustomExceptionFilter(EXCEPTION_POINTERS* ExceptionInfo) {
printf("Inside exception filter (GOOD)\n");
DWORD exceptionCode = (DWORD)ExceptionInfo->ExceptionRecord->ExceptionCode;
printf("Exception Code: 0x%X\n", exceptionCode);
if (exceptionCode == 0xE06D7363) { // code for C++ exception
printf("Exception code DOES match, GOOD\n");
}
else {
printf("Exception code DOES NOT match, BAD\n");
}
printf("Exception Address: 0x%llx\n", (ULONGLONG)ExceptionInfo->ExceptionRecord->ExceptionAddress);
printf("After printing exception: (GOOD)\n");
return EXCEPTION_EXECUTE_HANDLER;
}
int main() {
/*
* For this program, all subtests successful will print:
* - 3 'GOOD'
* - 0 'BAD'
*
* It is expected that the program terminates abnormally
* with status code 0xE06D7363 (C++ exception)
*/
// Set the custom top-level exception filter
SetUnhandledExceptionFilter(CustomExceptionFilter);
// Throw an unhandled exception.
// It should be caught by our filter.
throw (unsigned int)5;
// We should never reach this point, because the exception
// dispatcher should terminate the program after our unhandled
// exception filter is called.
printf("After exception filter (BAD)\n");
return 0;
}
@@ -0,0 +1,21 @@
#include <iostream>
#include <cstdio>
int main()
{
/*
* For this program, all subtests successful will print:
* - 1 'GOOD'
* - 0 'BAD'
*
* It is expected that the program terminates abnormally
* with status code 0xC0000409 (stack buffer overrun/security
* check failure)
*/
printf("Before throw (GOOD)\n");
throw (unsigned int)5;
printf("After throw (BAD)\n");
}
@@ -0,0 +1,93 @@
#include <iostream>
struct TestStruct {
float q;
};
class TestClass {
public:
int x, y;
virtual ~TestClass() {
std::cout << "TestClass destructor, GOOD" << std::endl;
};
void yyy() {
std::cout << "REALLY GOOD" << std::endl;
}
};
class Something {
public:
char z;
virtual ~Something() {
std::cout << "Something destructor, GOOD" << std::endl;
};
virtual void zzz() {
std::cout << "BAD" << std::endl;
};
};
class TestClass2 : public TestClass, public Something {
public:
int z;
virtual ~TestClass2() {
std::cout << "TestClass2 destructor, GOOD" << std::endl;
};
virtual void zzz() {
std::cout << "GOOD" << std::endl;
};
};
int main()
{
/*
* For this program, all subtests successful will print:
* - 12 'GOOD'
* - 0 'BAD'
*/
int x = 5;
TestClass p;
TestStruct s;
std::cout << typeid(x).name() << std::endl;
if (strcmp(typeid(x).name(), "int") == 0) {
std::cout << "typeid(x) is int, GOOD" << std::endl;
}
else {
std::cout << "typeid(x) is NOT int, BAD" << std::endl;
}
std::cout << typeid(p).name() << std::endl;
if (strcmp(typeid(p).name(), "class TestClass") == 0) {
std::cout << "typeid(p) is \"class TestClass\", GOOD" << std::endl;
}
else {
std::cout << "typeid(p) is NOT \"class TestClass\", BAD" << std::endl;
}
std::cout << typeid(s).name() << std::endl;
if (strcmp(typeid(s).name(), "struct TestStruct") == 0) {
std::cout << "typeid(s) is \"struct TestStruct\", GOOD" << std::endl;
}
else {
std::cout << "typeid(s) is NOT \"struct TestStruct\", BAD" << std::endl;
}
std::cout << "Reached virtual methods and dynamic_cast test. GOOD" << std::endl;
TestClass2* kz = new TestClass2;
Something* ks = static_cast<Something*>(kz);
ks->zzz();
TestClass* pk = dynamic_cast<TestClass*>(ks);
pk->yyy();
std::cout << "Reached virtual destructor test. GOOD" << std::endl;
delete pk;
std::cout << "Finished all tests. GOOD" << std::endl;
}
@@ -0,0 +1,45 @@
#include <windows.h>
#include <cstdio>
void test1() {
__try {
printf("Inside __try block. (GOOD)\n");
RaiseException(
0xE0000001,
0,
0,
nullptr
);
printf("After RaiseException. (BAD)\n");
}
__except (EXCEPTION_EXECUTE_HANDLER) {
printf("In __except block. (GOOD)\n");
unsigned long excepCode = GetExceptionCode();
printf("Exception code=0x%x\n", excepCode);
if (excepCode == 0xE0000001) {
printf("Exception code IS same, GOOD\n");
}
else {
printf("Exception code DOES NOT MATCH, BAD\n");
}
}
printf("After __except block. (GOOD)\n");
}
int main() {
/*
* For this program, all subtests successful will print:
* - 4 'GOOD'
* - 0 'BAD'
*/
test1();
return 0;
}
+2
View File
@@ -78,6 +78,8 @@ def my_sandbox(path, rootfs):
ql.os.set_syscall('vfork', __vfork)
os.unlink(fr'{ROOTFS}/proc/sys/kernel/core_pattern')
ql.run()
+2
View File
@@ -1,6 +1,8 @@
[CODE]
ram_size = 0xa00000
load_address = 0x80800000
entry_point = 0x80800000
heap_address = 0xa0000000
heap_size = 0x300000