SMALL
에뮬레이션 엔진인 Unicorn 활용
단한 Shellcode나 특정 함수 퍼징 수행할때 사용
The task is to call super_function in a way that it will return 1.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | int strcmp(char *a, char *b) { //get length int len = 0; char *ptr = a; while(*ptr) { ptr++; len++; } //comparestrings for(int i=0; i<=len; i++) { if (a[i]!=b[i]) return 1; } return 0; } __attribute__((stdcall)) int super_function(int a, char *b) { if (a==5 && !strcmp(b, "batman")) { return 1; } return 0; } int main() { super_function(1, "spiderman"); } | cs |
컴파일은 다음과 같이 수행
gcc function.c -m32 -o function
해당 프로그램에서 에뮬레이션 시켜서 return 1의 결과 값 가져오기기
밑에 부분은 디스어셈한 부분
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 0804845f <super_function>: 804845f: 55 push %ebp 8048460: 89 e5 mov %esp,%ebp 8048462: 83 7d 08 05 cmpl $0x5,0x8(%ebp) 8048466: 75 1b jne 8048483 <super_function+0x24> 8048468: 68 30 85 04 08 push $0x8048530 804846d: ff 75 0c pushl 0xc(%ebp) 8048470: e8 86 ff ff ff call 80483fb <strcmp> 8048475: 83 c4 08 add $0x8,%esp 8048478: 85 c0 test %eax,%eax 804847a: 75 07 jne 8048483 <super_function+0x24> 804847c: b8 01 00 00 00 mov $0x1,%eax 8048481: eb 05 jmp 8048488 <super_function+0x29> 8048483: b8 00 00 00 00 mov $0x0,%eax 8048488: c9 leave 8048489: c2 08 00 ret $0x8 | cs |
풀이 코드
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | from unicorn import * from unicorn.x86_const import * import struct from capstone import * import sys def read(name): with open(name) as f: return f.read() def u32(data): return struct.unpack("I", data)[0] def p32(num): return struct.pack("I", num) BASE_ADDR = 0x8048000 STACK_ADDR = 0x0 STACK_SIZE = 1024 * 1024 DATA_ADDR = 0x2000000 CS = Cs(CS_ARCH_X86, CS_MODE_32) def bypass(mu, address, size, user_data): mu.reg_write(UC_X86_REG_EIP, address + size) def handler(mu, address, size, user_data): print hex(address), ins = CS.disasm(mu.mem_read(address, size), size) i = list(ins)[0] print("0x%x:\t%s\t%s" %(i.address, i.mnemonic, i.op_str)) def solver(): # First : main architecture # Second : further architecture specification mu = Uc (UC_ARCH_X86, UC_MODE_32) #Memory Mapping mu.mem_map(BASE_ADDR, 1024*1024) # code Area mu.mem_map(STACK_ADDR, STACK_SIZE) # stack Area mu.mem_map(DATA_ADDR, 0x1000) # DATA Area TARGET = read('./task2') #Write Data mu.mem_write(BASE_ADDR, TARGET) mu.mem_write(DATA_ADDR, 'batman\x00') #Set ESP Register mu.reg_write(UC_X86_REG_ESP, int(STACK_SIZE)/3) #Hook code inser #our own function hook_codethat is called before emulation of each instruction mu.hook_add(UC_HOOK_CODE, handler) #if program access unmapped area, bypass functioin execute mu.hook_add(UC_HOOK_MEM_WRITE_UNMAPPED, bypass) mu.hook_add(UC_ERR_READ_UNMAPPED,bypass) r_esp = mu.reg_read(UC_X86_REG_ESP) #Argument ARG1,2 mu.mem_write(r_esp+4,p32(5)) mu.mem_write(r_esp+8, p32(0x2000000)) mu.emu_start(0x804845f, 0x8048489) print mu.reg_read(UC_X86_REG_EAX,) sys.exit() def main(): print "[*] Unicorn Enginie Tutorial" solver() if __name__ == '__main__': main() | cs |
출처 : http://eternal.red/2018/unicorn-engine-tutorial/
LIST
'reversing > reversing' 카테고리의 다른 글
mips 특징 (0) | 2018.10.08 |
---|---|
chroot qemu static 환경변수 설정 (0) | 2018.10.07 |
디바이스 동적분석 환경 구축 [1] - Pro1 (0) | 2018.07.24 |
SCTF Rev[100] (0) | 2018.07.07 |
GO 언어 리버싱 (0) | 2018.06.12 |