NAME
CGCABI - CGC Application Binary Interface
SYNOPSIS
#include <libcgc.h>
DESCRIPTION
This document details the Application Binary Interface (ABI) interface used by to CGC Challenge binaries to access system calls and the initial state of registers when a binary is loaded.
The ABI and system calls have been designed to create a minimal number of system entry points that allows for the creation of CGC Challenge Binaries that reflect real world services and allow authors to inject memory corruption vulnerabilities consistent with the stated goals of the CGC program.
Challenge binaries are run in an Intel 32bit Architecture (IA32) protected mode, flat memory model execution environment.
System Calls
The following system calls may be present in a CGC binary execution environment. With few exceptions, these system calls adhere to the POSIX semantics associated with each corresponding system call as implemented on the Linux operating system. Each system call below is fully described in its own manual page.
Name | Number |
---|---|
_terminate |
1 |
transmit |
2 |
receive |
3 |
fdwait |
4 |
allocate |
5 |
deallocate |
6 |
random |
7 |
A prototype for each system call is given in libcgc.h
and a reference
implementation can be found in libcgc.a
.
System Call ABI
The CGC application binary interface is specific to compatible x86-32 bit CGC execution environments. In order to invoke a CGC system call, the system call number must be placed in the eax register. Arguments to a system call function are passed via registers ebx, ecx, edx, esi, edi, and ebp as summarized in the following table:
Register | Purpose |
---|---|
eax |
Contains system call number |
ebx |
First argument to function |
ecx |
Second argument to function (if required) |
edx |
Third argument to function (if required) |
esi |
Fourth argument to function (if required) |
edi |
Fifth argument to function (if required) |
ebp |
Sixth argument to function (if required) |
Invocation of a system call function is accomplished through the use of
the int 0x80
instruction. All system calls that return, return a
status code in the eax register. A zero status indicates a successful
system call. A non-zero status indicates an error and the specific
error number is contained in the eax
register. For system calls that
return a value, the return value is provided to the caller via a caller
supplied pointer parameter. See descriptions of individual system calls
for more detailed information on both status codes and required
parameters. If eax
contains an invalid system call number upon entry to
the kernel, the status ENOSYS
shall be returned.
Invalid Instructions
The following instructions have undefined behavior if used in a CGC
Challenge Binary: rdpmc
, rdrand
, rdtsc
, and rdtscp
, and sysenter
.
Signals
Traditional POSIX signals are not supported by CGC Challenge Binaries.
A CB process receiving a signal is killed by the kernel and a core
file may be produced. An exception to this rule is SIGPIPE
. Normally,
SIGPIPE
sent to a process kills the process. A SIGPIPE
results in a
system call returning EPIPE
.
Constants / Defines
Several constants, structures, and macros are defined in libcgc.h
for use by CBs. The definitions of these symbols may not be the
same as the host operating system.
Symbol |
---|
EBADF |
EFAULT |
EINVAL |
ENOMEM |
ENOSYS |
EPIPE |
FD_CLR |
FD_ISSET |
_fd_mask |
fd_set |
FD_SET |
FD_SETSIZE |
FD_ZERO |
_NFDBITS |
NULL |
SIZE_MAX |
size_t |
SSIZE_MAX |
ssize_t |
STDERR |
STDIN |
STDOUT |
timeval |
Initial State
The initial state of the various processor and coprocessor registers are given below.
Initial General Purpose Register State
Register | Value |
---|---|
EAX |
0 |
EBX |
0 |
ECX |
The ECX register contains a pointer to a page-aligned address filled with random data. The special flag page is read-only and it is not permitted to be deallocated. |
EDX |
0 |
EDI |
0 |
ESI |
0 |
ESP |
0xbaaaaffc |
EBP |
0 |
EIP |
EIP is set to the value of `c_entry" specified in the header of the CGC binary being loaded. |
EFLAGS |
0x202 |
CS |
The values of the segment registers are not specified; however, the CS , DS , and SS registers will be set to correctly execute the CB and DS = ES = FS = GS = SS |
DS |
The values of the segment registers are not specified; however, the CS , DS , and SS registers will be set to correctly execute the CB and DS = ES = FS = GS = SS |
ES |
DS |
FS |
DS |
GS |
DS |
SS |
DS |
The value of the EFLAGS
register means that interrupts are enabled
(bit 9 set). Bit 1 is always set.
Initial Floating Point Unit Register State
Register | Value |
---|---|
Control | 0x037f |
Status | 0 |
Tag | 0xffff |
Opcode | 0 |
Instruction Pointer | 0 |
Data Pointer | 0 |
R0 , R1 , R2 , R3 |
0 |
R4 , R5 , R6 , R7 |
0 |
The Control register value is decoded as follows:
Bits | Value | Description |
---|---|---|
rounding control | 0 | round closes to infinitely precise result, if equal, round to even least significant bit |
precision control | 3 | double extended precision |
all exceptions | 0 | masked |
The tag register encoding just states that all fpu stack positions are empty (b'11 for all eight registers).
Initial MMX register state
The initial MMX register state is the same as the state of FPU since the registers are aliased to the same storage.
Initial XMM Register State (SSE)
Register | Value |
---|---|
MXCSR | 0x1f80 |
XMM0 … XMM15 | 0 |
The MXCSR is decoded as follows: flush to zero: disabled, rounding control = 0 (same as FPU, above), all exceptions masked, no exceptions currently flagged
Memory Layout
When a CB is loaded, the PT_LOAD
sections of the binary describe the
layout of the binary in the 32bit virtual address space. The permissions
of pages loaded by the binary are as specified (all pages are readable,
but may also be executable and/or writeable).
An initial stack is allocated for the process beginning from 0xbaaaaffc and going down. Stack pages are automatically allocated by the kernel on behalf of the process. All stack pages are readable, writable, and executable. Processes are allowed a maximum stack size of 8MB.
The data segment (program text section, readonly section, bss, and
read/write section), is limited to 1GB. This does not include memory
allocated by the allocate(2)
system call.
There is no equivalent of argc
, argv
, envp
normally provided by the
kernel to a process. The stack region is filled with zeroes as it
is allocated and when execution begins at %eip, (%esp) = 0
.
Math Functions
The CGC library contains definitions for a variety of math functions for which acceleration is available on the processor but would require assembly language to access. Those functions are as follows.
/* sine(x), where x is in radians */
float sinf(float);
double sin(double);
long double sinl(long double);
/* cosine(x), where x is in radians */
float cosf(float);
double cos(double);
long double cosl(long double);
/* tangent(x), where x is in radians */
float tanf(float);
double tan(double);
long double tanl(long double);
/* arctangent(y, x): arctangent of y/x in radians */
float atan2f(float, float);
double atan2(double, double);
long double atan2l(long double, long double);
/* square root */
float sqrtf(float);
double sqrt(double);
long double sqrtl(long double);
/* round to integral value */
float rintf(float);
double rint(double);
long double rintl(long double);
/* absolute value */
float fabsf(float);
double fabs(double);
long double fabsl(long double);
/* remainder(x,y): returns r = x - n * y where */
/* n is the integer closest to x/y */
float remainderf(float, float);
double remainder(double, double);
long double remainderl(long double, long double);
/* scalbn(x,y): scale x by power of 2**y: x * (2**y) */
float scalbnf(float, int);
double scalbn(double, int);
long double scalbnl(long double, int);
float scalblnf(float, long int);
double scalbln(double, long int);
long double scalblnl(long double, long int);
/* significand(x): mantissa of x */
float significandf(float);
double significand(double);
long double significandl(long double);
/* base 2 logarithm */
float log2f(float);
double log2(double);
long double log2l(long double);
/* natural logarithm */
float logf(float);
double log(double);
long double logl(long double);
/* base 10 logarithm */
float log10f(float);
double log10(double);
long double log10l(long double);
/* base 2 exponential */
float exp2f(float);
double exp2(double);
long double exp2l(long double);
/* natural (base e) exponential */
float expf(float);
double exp(double);
long double expl(long double);
/* pow(x,y) = x**y */
float powf(float, float);
double pow(double, double);
long double powl(long double, long double);
Other Functions
In addition to the system calls and math functions, two additional
functions are provided by the CGC ABI: setjmp()
and longjmp()
. These
functions allow for saving processor state and restoring it at some
point in the future. Their behavior is meant to mimic the behavior
of these functions available in other operating systems.
CAVEATS
The pow()
functions are not conformant with C99. For instance,
they return NaN
for infinite exponents and for finite negative
bases with finite integer exponents.
SEE ALSO
allocate(2), deallocate(2), fdwait(2), random(2), receive(2), _terminate(2), transmit(2), cgc_executable_format(1), core(5).
FILES
/usr/include/libcgc.h
/usr/lib/libcgc.a