Skip to content

Commit

Permalink
teach fac to cross-compile to windows
Browse files Browse the repository at this point in the history
  • Loading branch information
droundy committed Jun 14, 2016
1 parent 3ae60cd commit eabc5a7
Show file tree
Hide file tree
Showing 13 changed files with 333 additions and 36 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,6 @@ web
*.gcno
*.exe
win32/helper.h
win32/bigbro32.h
win32/bigbro64.h
*.dll
27 changes: 0 additions & 27 deletions appveyor.yml

This file was deleted.

4 changes: 3 additions & 1 deletion bigbro-windows.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ int bigbro(const char *workingdir, pid_t *child_ptr,
printf("Error allocating shared memory.\n");
return 1;
}
char *new_windows_env = 0;
if (envp) {
// create an environment with the desired environment variables,
// plus one more to carry the name of our shared-memory segment.
Expand Down Expand Up @@ -104,5 +103,8 @@ int bigbro(const char *workingdir, pid_t *child_ptr,
*read_from_files = hashset_to_array(&read);
*read_from_directories = hashset_to_array(&readdir);
*written_to_files = hashset_to_array(&written);
free_hashset(&read);
free_hashset(&readdir);
free_hashset(&written);
return dword_return_code;
}
7 changes: 6 additions & 1 deletion build/binary2header.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
def convertFile(binary_filename, header_filename, variable_name):
with open(binary_filename, 'rb') as b:
with open(header_filename, 'w') as h:
h.write('''static unsigned char %s[] = { ''' % variable_name);
h.write('''static const unsigned char %s[] = { ''' % variable_name);
stuff = b.read()
h.write(',\n'.join('%d' % ord(stuff[i:i+1]) for i in range(len(stuff))))
h.write('\n};\n')

if __name__ == "__main__":
# we are running this as a script
import sys
convertFile(sys.argv[1], sys.argv[2], sys.argv[3])
40 changes: 40 additions & 0 deletions build/cross-windows.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#!/bin/sh

set -ev

(x86_64-w64-mingw32-gcc -Wall -Werror -std=c99 -g -O2 -c -o bigbro-windows.obj bigbro-windows.c)

(x86_64-w64-mingw32-gcc -Wall -Werror -std=c99 -g -O2 -c -o fileaccesses.obj fileaccesses.c)

(i686-w64-mingw32-gcc -Wall -Werror -std=c99 -g -O2 -c -o win32/helper32.obj win32/helper.c)

(i686-w64-mingw32-gcc -o win32/helper.exe win32/helper32.obj)

(python3 build/binary2header.py win32/helper.exe win32/helper.h helper)

(x86_64-w64-mingw32-gcc -Wall -Werror -std=c99 -g -O2 -c -o win32/inject.obj win32/inject.c)

(x86_64-w64-mingw32-gcc -Wall -Werror -std=c99 -g -O2 -c -o win32/queue.obj win32/queue.c)

(x86_64-w64-mingw32-gcc -Wall -Werror -std=c99 -g -O2 -o bigbro.exe bigbro-windows.obj fileaccesses.obj win32/inject.obj win32/queue.obj)

(i686-w64-mingw32-gcc -Wall -Werror -std=c99 -g -O2 -c -o win32/dll32.obj win32/dll.c)

(i686-w64-mingw32-gcc -Wall -Werror -std=c99 -g -O2 -c -o win32/hooks32.obj win32/hooks.c)

(i686-w64-mingw32-gcc -Wall -Werror -std=c99 -g -O2 -c -o win32/inject32.obj win32/inject.c)

(i686-w64-mingw32-gcc -Wall -Werror -std=c99 -g -O2 -c -o win32/patch32.obj win32/patch.c)

(i686-w64-mingw32-gcc -Wall -Werror -std=c99 -g -O2 -c -o win32/queue32.obj win32/queue.c)

(i686-w64-mingw32-gcc -shared -o bigbro32.dll win32/inject32.obj win32/dll32.obj win32/patch32.obj win32/hooks32.obj win32/queue32.obj -lntdll -lpsapi)

(x86_64-w64-mingw32-gcc -Wall -Werror -std=c99 -g -O2 -c -o win32/dll.obj win32/dll.c)

(x86_64-w64-mingw32-gcc -Wall -Werror -std=c99 -g -O2 -c -o win32/hooks.obj win32/hooks.c)

(x86_64-w64-mingw32-gcc -Wall -Werror -std=c99 -g -O2 -c -o win32/patch.obj win32/patch.c)

(x86_64-w64-mingw32-gcc -shared -o bigbro64.dll win32/inject.obj win32/dll.obj win32/patch.obj win32/hooks.obj win32/queue.obj -lntdll -lpsapi)

1 change: 1 addition & 0 deletions configure.fac
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
| python3 configure.py > .fac
> .fac
c .pyc

| python3 syscalls/linux.py > syscalls/linux.h
> syscalls/linux.h
Expand Down
105 changes: 103 additions & 2 deletions configure.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,22 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301 USA

import string, os, glob, sys
import string, os, glob, sys, importlib

def is_in_path(program):
""" Does the program exist in the PATH? """
def is_exe(fpath):
return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
fpath, fname = os.path.split(program)
if fpath:
return is_exe(program)
else:
for path in os.environ["PATH"].split(os.pathsep):
path = path.strip('"')
exe_file = os.path.join(path, program)
if is_exe(exe_file):
return True
return False

platform = sys.platform
if platform == 'linux2':
Expand All @@ -41,7 +56,6 @@
cflags += ' ' + flag
else:
print('# %s cannot use flag: %s' % (cc, flag))
os.system('rm -rf testing-flags')

print('# cc=', repr(cc)) # in future, we should set this dynamically
print('# cflags=', repr(cflags))
Expand All @@ -64,3 +78,90 @@
< libbigbro.a
> bigbro
""" % (cc, cflags))

wincfiles = ['bigbro-windows.c', 'fileaccesses.c', 'win32/inject.c', 'win32/queue.c']
dll_cfiles = ['win32/inject.c', 'win32/dll.c', 'win32/patch.c', 'win32/hooks.c',
'win32/queue.c', 'win32/path.c']

if is_in_path('i686-w64-mingw32-gcc'):
print('\n# We have a 32-bit mingw compiler, so let us cross-compile for windows!\n')

cflags = ''
for flag in ['-Wall', '-Werror', '-std=c99', '-g', '-O2']:
if not os.system('cd testing-flags && i686-w64-mingw32-gcc %s %s -c test.c' %
(cflags, flag)):
cflags += ' ' + flag
else:
print('# i686-w64-mingw32-gcc cannot use flag: %s' % flag)

print('''
# first build the helper executable
| i686-w64-mingw32-gcc %s -c -o win32/helper32.obj win32/helper.c
| i686-w64-mingw32-gcc -o win32/helper.exe win32/helper32.obj
< win32/helper32.obj
# now convert this executable into a header file
| python3 build/binary2header.py win32/helper.exe win32/helper.h helper
< win32/helper.exe
''' % (cflags))

for c in dll_cfiles:
print("""
| i686-w64-mingw32-gcc %s -c -o %s32.obj %s
""" % (cflags, c[:-2], c))

print('''
| i686-w64-mingw32-gcc -shared -o bigbro32.dll %s -lntdll -lpsapi'''
% ' '.join([c[:-2]+'32.obj' for c in dll_cfiles]))
for c in dll_cfiles:
print("< %s32.obj" % c[:-2])

if is_in_path('x86_64-w64-mingw32-gcc'):
print('\n# We have a 64-bit mingw compiler, so let us cross-compile for windows!\n')

cflags = ''
for flag in ['-Wall', '-Werror', '-std=c99', '-g', '-O2']:
if not os.system('cd testing-flags && x86_64-w64-mingw32-gcc %s %s -c test.c' %
(cflags, flag)):
cflags += ' ' + flag
else:
print('# x86_64-w64-mingw32-gcc cannot use flag: %s' % flag)

for c in set(dll_cfiles+wincfiles):
print("""
| x86_64-w64-mingw32-gcc %s -c -o %s.obj %s
> %s.obj
""" % (cflags, c[:-2], c, c[:-2]))

print('''
| x86_64-w64-mingw32-gcc -shared -o bigbro64.dll %s -lntdll -lpsapi'''
% ' '.join([c[:-2]+'.obj' for c in dll_cfiles]))
for c in dll_cfiles:
print("< %s.obj" % c[:-2])

print('''
# convert the dlls into into header files
| python3 build/binary2header.py bigbro32.dll win32/bigbro32.h bigbro32dll
< bigbro32.dll
| python3 build/binary2header.py bigbro64.dll win32/bigbro64.h bigbro64dll
< bigbro64.dll
''')

print("""
| x86_64-w64-mingw32-gcc %s -o bigbro.exe %s"""
% (cflags, ' '.join([c[:-1]+'obj' for c in wincfiles])))
for c in wincfiles:
print("< %s.obj" % c[:-2])

for c in glob.glob('tests/*.c'):
base = c[:-2]
m = importlib.import_module('tests.'+base[6:])
if 'skip_windows' in dir(m):
print('# skipping test', base, 'not supported by windows')
else:
print("""
| x86_64-w64-mingw32-gcc %s -o %s-test.exe %s"""
% (cflags, c[:-2], c))

os.system('rm -rf testing-flags')
2 changes: 2 additions & 0 deletions run-tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@
print('==========================')
if not os.system('fac --help'):
assert not os.system('fac --script build/%s.sh libbigbro.a bigbro' % platform)
if not os.system('fac --help'):
os.system('fac --script build/cross-windows.sh bigbro.exe bigbro32.dll bigbro64.dll')

print('building bigbro by running build/%s.sh...' % platform)
print('============================================')
Expand Down
7 changes: 7 additions & 0 deletions tests/fopen.c
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
#include <stdio.h>

int main() {
printf("creating the file...\n");
FILE *f = fopen("tmp/foo", "w");
printf("writing to the file...\n");
fprintf(f, "this is good\n");
printf("closing the file...\n");
fclose(f);
printf("I am about to open the file...\n");
f = fopen("tmp/Foo", "r");
printf("I am about to finally close the file...\n");
if (f) fclose(f);
return 0;
}
62 changes: 60 additions & 2 deletions win32/hooks.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,68 @@
NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */

// We need to assert that we are running on Vista or later in order to
// get the GetFinalPathNameByHandleW declaration.
#define _WIN32_WINNT 0x0600

#include <windows.h>
#include <winternl.h>
#include <limits.h>
#include <wchar.h>

#undef ASSERT
/* #include "handle.h" */
/* #include "utf8.h" */
#include "patch.h"
#include "inject.h"
#include "hooks.h"
#include "queue.h"
#include "path.h"
#include "../errors.h"

#ifndef PATH_MAX
#define PATH_MAX 4096
#endif

// Convert a wide Unicode string to an UTF8 string
void utf8_encode(char *buf, int buflen, const wchar_t *input, int inputlen) {
if (inputlen == 0) {
*buf = 0;
return;
}
WideCharToMultiByte(CP_UTF8, 0, input, inputlen, buf, buflen, NULL, NULL);
}

// Convert an UTF8 string to a wide Unicode String
void utf8_decode(wchar_t *buf, int buflen, const char *input, int inputlen) {
if (inputlen == 0) {
*buf = 0;
return;
}
MultiByteToWideChar(CP_UTF8, 0, input, inputlen, buf, buflen);
}

static char *utf8PathFromWide(char *buf, const PWSTR s, int sl) {
if (sl <= 0) return 0;
int l;
l = WideCharToMultiByte(CP_UTF8, 0, s, sl, buf, PATH_MAX, 0, 0);
if (l == 0) return 0;
buf[l] = 0;
if (!buf[0]) return 0;
/* if (buf[0] == '\\' && !strchr(buf, ':')) return 0; */
/* if (strncmp(buf, "\\\\?\\", 4) == 0 || strncmp(buf, "\\??\\", 4) == 0) */
/* return buf + 4; */
return buf;
}

static inline char *handlePath(char *dst, HANDLE h) {
WCHAR wbuf[PATH_MAX];
int len = GetFinalPathNameByHandleW(h, wbuf, PATH_MAX, FILE_NAME_NORMALIZED);
printf("len of final path is %d from handle %p\n", len, h);
if (len <= 0 || len >= PATH_MAX) return 0;
return utf8PathFromWide(dst, wbuf, len);
}

#define HOOK(n) static NTSTATUS(NTAPI *o##n)()
HOOK(NtCreateFile);
HOOK(NtOpenFile);
Expand Down Expand Up @@ -111,7 +157,20 @@ static NTSTATUS NTAPI hNtCreateFile(PHANDLE ph,
r = oNtCreateFile(ph, am, oa, sb, as, fa, sa, cd, co, bu, le);
if (NT_SUCCESS(r)) {
debugprintf("am in hNtCreateFile!\n");
femit(*ph, fop(co, am));
char buf[4096];
utf8PathFromWide(buf, oa->ObjectName->Buffer, oa->ObjectName->Length/2);
printf("\nI am in hNtCreateFile %s!\n", buf);
// char *p = GetFileNameFromHandle(ph);
char *p = handlePath(buf, ph);
printf("I am in hNtCreateFile with path %p!\n", p);
printf("I am in hNtCreateFile with string %s!\n", p);
if (p) {
queueOp(WRITE_OP, p);
femit(*ph, fop(co, am));
free(p);
} else {
printf("skipping null path pointer!\n");
}
}
return r;
}
Expand All @@ -134,7 +193,6 @@ static NTSTATUS NTAPI hNtOpenFile(PHANDLE ph,
static NTSTATUS NTAPI hNtDeleteFile(POBJECT_ATTRIBUTES oa) {
NTSTATUS r;
debugprintf("am in hNtDeleteFile!\n");
char buf[PATH_MAX];
r = oNtDeleteFile(oa);
if (NT_SUCCESS(r)) {
/* emitOp('d', utf8PathFromWide(buf, oa->ObjectName->Buffer, oa->ObjectName->Length/2), 0); */
Expand Down

0 comments on commit eabc5a7

Please sign in to comment.