#!/usr/bin/python2
import os, sys, time, random
import subprocess, traceback

FLAG = '********* erased **********'

source_code = '''
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <seccomp.h>
#include <sys/prctl.h>

void sandbox(){{
	scmp_filter_ctx ctx = seccomp_init(SCMP_ACT_ALLOW);
	if (ctx == NULL) {{
		printf("seccomp error\\n");
		exit(0);
	}}

	seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(connect), 0);
	seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(dup), 0);
	seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(dup2), 0);
	seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(dup3), 0);
	seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(open), 0);
	seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(openat), 0);
	seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(execve), 0);

	if (seccomp_load(ctx) < 0) {{
		seccomp_release(ctx);
		printf("seccomp error\\n");
		exit(0);
	}}
	seccomp_release(ctx);
}}

unsigned long long rdtsc(){{
	unsigned long lo, hi;
        asm( "rdtsc" : "=a" (lo), "=d" (hi) ); 
        return( lo | (hi << 32) );
}}

void A(){{
	asm("{0}");
}}

void B(){{
	asm("{1}");
}}

unsigned long long measure_time(void (*f)(), int cnt){{
	register int i = cnt;
	unsigned long long t2, t1;
	t1 = rdtsc();
	prctl(PR_SET_TSC, PR_TSC_SIGSEGV);
	while(i--) f();
	prctl(PR_SET_TSC, PR_TSC_ENABLE);
	t2 = rdtsc();
	return t2-t1;
}}

int main(int argc, char* argv[]){{

	unsigned long long t_A=0, t_B=0;
	void* p = mmap((void*)0x66666000, 0x1000, PROT_WRITE|PROT_READ|PROT_EXEC, MAP_ANONYMOUS|MAP_SHARED, -1, 0);

	sandbox();	

	measure_time(A, 10);		// warm up cache
	t_A = measure_time(A, 10000);

	measure_time(B, 10);		// warm up cache
	t_B = measure_time(B, 10000);

	if( t_A > t_B*1.2 ){{
		printf("emulator! (A:%llu, B:%llu)\\n", t_A, t_B);
	}}
	else if( t_B > t_A*1.2 ){{
		printf("realcpu! (A:%llu, B:%llu)\\n", t_A, t_B);
	}}
	else{{
		printf("im not sure... (A:%llu, B:%llu)\\n", t_A, t_B);
	}}

	return 0;
}}
'''

black_list  = ['jne', 'je', 'jmp', 'ret', 'and', 'mov', 'push', 'pop', 'xor', 'loop', 'sh']
black_list += ['"', '/', '#', '(', ')', '*', '&', '\'', '\n', '\t', '\x00', '@', '^', '+']
black_list += ['sub', 'add', 'jz', 'jnz', 'byte', 'int', '80', 'leave', 'syscall', 'xchg', 'nop']

def check( code ):
	for e in black_list:
		if code.lower().find(e) != -1: return False
	if len(code) > 40: return False

def compile_code( nonce ):
	global source_code
	with open('/tmp/{0}.c'.format(nonce), 'wb') as f:
		f.write( source_code )
	try:
		os.system('gcc -o /tmp/{0} /tmp/{0}.c -fPIC -pie -lseccomp'.format(nonce))
		if os.path.isfile('/tmp/{0}'.format(nonce)) == False: raise 1
        except:
                print sys.exc_info()
                os.system('rm /tmp/{0}.c'.format(nonce))
                print 'your code has syntax error :('
		raise 1
        return '/tmp/{0}'.format(nonce)

def emu_detect( name, is_emu ):
	try:
		DEVNULL = open(os.devnull, 'w')
		if is_emu==True :
			p = subprocess.Popen(['/usr/bin/qemu-x86_64', name], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=DEVNULL)
		else:
			p = subprocess.Popen(name, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=DEVNULL)
		output = p.stdout.readline()
	except:
		print 'unknown error occured'
		raise 1
	return output

if __name__ == '__main__':
	print '''
	---------------------------------------------------
	-              Shall we play a game?              -
	---------------------------------------------------
	
	Hey man, I'm writing a malware to steal some bank account :)
	anyway, I want to put some timing based emulator detection 
	logic into my malware. but the malware emulators are becoming 
	fast and smart in these days :(	so simple timing check to see 
	if 'RDTSC count is big' stuffs won't work accurately. 

	I want to make code A and B such that A is slower than B in 
	case of emulator but B is slower than A in case of real CPU

	can you make me such kind of x64 asm code?
	also, I want the detection code to be very small... 
	once your code bypasses my stupid filter, I'll evaluate the code.
	get me some magic code here :)

	'''
	sys.stdout.flush()
	time.sleep(1)

	try:
		sys.stdout.write('x64 asm code for function A: ')
		sys.stdout.flush()		
		code_A = raw_input()

		if check(code_A) == False: raise 1

                sys.stdout.write('x64 asm code for function B: ')
                sys.stdout.flush()
                code_B = raw_input()

		if check(code_B) == False: raise 1

		print 'got your code. let me see if it works...'
		source_code = source_code.format(code_A, code_B)
		sys.stdout.flush()

		time.sleep(1)

		bin_name = compile_code( random.randrange(100000000000000) )

		hit = 0
		for i in xrange(100):
			X = (random.randrange(2) == 0)
			if X: print 'running your code inside qemu-x86_64...'
			else: print 'running your code with real CPU...'
			result = emu_detect( bin_name, X )
			print 'your code says : ', result.strip()

			if X and result.find('emulator')!=-1 and result.find('realcpu')==-1 :
				hit += 1
				print 'correct!({0})'.format(hit)
			elif not X and result.find('realcpu')!=-1 and result.find('emulator')==-1  :
				hit += 1
				print 'correct!({0})'.format(hit)
			else:
				print 'wrong!'
			print '\n'
			sys.stdout.flush()

		if hit > 97:
			print 'dude...! your code is really awesome!'
			print 'thanks for the help. here is reward :)'
			print FLAG
		else:
			print 'im disappointed man... :('

		os.system('rm {0}.c'.format(bin_name))
		os.system('rm {0}'.format(bin_name))
		sys.stdout.flush()
	except:
		print 'you suck :P'
		sys.stdout.flush()
		os._exit(0)

	sys.stdout.flush()
	os._exit(0)

