PE relocation 

PE 파일은 프로세스 가상 메모리에 로딩되어질 때 PE 헤더의 'ImageBase'에 로딩되어짐.

그런데 ImageBase에 이미 다른 파일이 배치되어있을 경우에는 같은 주소 공간에 두개의 다른 파일을 로딩할 수는 없음.

따라서 PE 재배치를 통해 다른 주소에 로딩되게 함.

 

- 이전 EXE의 경우 가장 먼저 메모리에 올라갔기 때문에 재배치 고려를 하지 않았지만 현재쓰고있는 윈도우 버전의 경우엔 'ASLR' 기능이 추가되어서 EXE가 실행 되어질 때마다 랜덤한 주소에 로딩되어짐.

* 실제 재배치 작업 동작 원리

 

#1. 프로그램의 하드코딩된 주소를 써치

Base reloaction table을 통해서 찾는다. RVA가 1420일경웨 PE View를 통해 해당 주소의 내용을 확인한다.

1420의 하드코딩된 주소 08C28309 값이 들어있다.

 

#2. 값을 읽은 후 ImageBase만큼 뺀다(VA -> RVA)

 

08C28309 - 0100000 = 07C28309

 

#3. 실제 로딩 주소를 더한다.(RVA -> VA)

 

07C28309 + 00AF0000 (실제 로딩된 주소) = 08718309

 

PE 로더는 하드코딩된 주소 08C28309를 위와 같은 과정을 거쳐 보정된 값(08718309)을 같은 위치에 덮어씀!

이 과정을 하나의 Image_Base_reloaction 구조체의 모든 옵셋에 반복해서 적용하면 RVA 1000~2000 주소 영역에 해당하는 모든 하드코딩 주소에 대해서 PE 재배치 작업이 수행되어지게 되는것임!

 

.reloc 섹션

exe 파일에서 base_relocation_table은 필수적이지 않음. 그러나 dll,sys는 거의 필수적임.

.reloc는 VC++에서 생성한 PE의 맨 마지막에 위치한다고 함.

 

reloc.exe의 .reloc 섹션을 제거하기 위해서 다음의 4가지 단계를 거쳐야 함.

 

1. .reloc 섹션 헤더 정리

2. .reloc 섹션 제거

3. Image_file_header 수정

4. Image_optional_header 수정

가즈아!

 

#1. .reloc 섹션 헤더 정리

.reloc은 offset 270에서 시작함. 해당 부분을 0으로 덮어씁니다.

이 부분을 0으로
헤더 제거 완료

#2. reloc 섹션 제거

위 그림을 살펴보면 reloc 섹션의 시작 옵셋은 C000 입니다. 이 부분부터 파일의 끝까지 삭제합니다.

삭제완료

#3. Image_file_header 수정

 

섹션을 하나 삭제 했기 때문에 헤더에 섹션 개수를 나타내주는 Number_of_sections 항목을 수정합니다.

5에서 4로 수정!

#4. Image_optional_header 수정

섹션을 삭제해 그 크기만큼 이미지 크기가 줄어들었으므로 이미지 크기도 조절해줘야함.

현재 size_of_image값 11000에서 얼마만큼 빼야하냐면 삭제한 섹션(.reloc)의 Virtual Size는 E40이였음 이걸 

Section Alignment에 맞게 확장하면 1000임 따라서 1000을 빼줘야함.

 

다음으로는 자신의 섹션을 추가해보는 연습을 해볼 것.

섹션 추가 연습

의문점 ? Size of Raw Data랑 Virtual Size의 값이 다른거는 알겠다. 실제 옵셋이랑 메모리에 로딩되었을 때랑 일반적으로 다르다고 하니까. 그런데 vitual size값은 어떻게 결정되는거지

 

위에사진에 디스크에서 200의 size인데 메모리에 올라간 경우 1B4라는 값을 가지는데 어떻게 계산되는지 모르겠당

 

 

'Reversing' 카테고리의 다른 글

리버싱 10  (0) 2019.04.11
리버싱 9  (0) 2019.04.10
리버싱 7  (0) 2019.04.05
리버싱 6  (2) 2019.04.04
PE file(3)  (0) 2019.04.03

실행 압축

먼저 압축을 3가지 방식으로 나눠봅니다.

 

#1. 비손실 압축

- 압축된 파일을 100% 원래대로 복원할 수 있다. (무결성 보장)

 

#2. 손실 압축

- 원래대로 복원할 수 없다.

- jpg, mp4 등에 사용되며 의도적인 손상을 주어서 압축률을 높임 (사람은 식별안됌)

 

#3. 실행 압축

- PE 파일을 대상으로 하는 압축

- 파일 내부에 압축해제 코드를 포함하고 있어, 실행되는 순간에 메모리에서 압축을 해제 후 실행시키는 기술.

- PE 파일을 실행 압축 파일로 만들어 주는 유틸을 '패커'라고 함.

 

* 패커의 사용 목적 : 크기를 줄일 수도 있지만 파일 내부의 코드와 리소스를 보호.

 

PE 프로텍터 : 단순히 압축을 목적이 아닌 안티 리버싱을 위해 다양한 기법들로 코드및 리소스를 보호함

 

notepad.exe를 UPX 패커를 이용해 패킹을 진행해보자 !

 

[UPX 다운로드]

내가 쓸 notepad_upx.exe

notepad_upx.exe
0.05MB

PE Viewer로 비교해보자!

notepad.exe와 notepad_upx.exe

 

음... 뭔가가 변화가 있는것 같다. UPX의 첫번째 섹션을 열어보면,

 

Virtual Size의 값은 1만인데 Raw Data Size값이 0이다.

이게 무슨 일이냐면 압축된 원본코드와 해제코드는 지금 섹션2에 존재합니다. 그런데 실행하게 될경우 이게 섹션 1에 해제 되어지는 것입니더.

 

그럼 디버깅!

 

notepad_upx.exe 디버깅

목표 : 코드를 하나씩 트레이싱 하면서 원본 코드를 찾아보za

 

먼저 원본코드의 구조를 확인하기 위해 원본파일인 notepad.exe를 열어보자.

 

먼저 010073B2의 주소에서 GetModuleHandleA() 함수를 호출해서 notepad.exe의 ImageBase를 구한다.

그 후에 010073B4와 010073C0에서 각각 MZ와 PE 시그니처를 비교합니다. 

 

이제 notepad_upx.exe를 열어보자!

 

짜짱!

01015330이 EP 주소입니다. 여기는 2번째 섹션의 끝부분 주소입니다. 실제 원본코드는 이 주소 위로 존재합니다.

하나씩 살펴볼까요 ~

 

먼저 PUSHAD를 통해 EAX~EDI 레지스터 값을 스택에 저장하고,

ESI, EDI레지스터를 각각 두 번째와 첫 번째 섹션의 시작주소로 설정합니다. (0101100, 01001000)

- 이렇게 esi와 edi가 동시에 세팅되면 esi -> edi 로 메모리 복사가 일어날 거라 추측.

esi에서 데이터를 읽어서 압축을 해제한 후 edi에 저장.

 

그럼 트레이싱을 시작하자 트레이싱 단축키! (* 루프를 만나면 루프를 확인하고 넘어간다)

- 총 4개의 루프를 만날 예정

[Ctrl + F8]을 누르면 정신없이 트레이싱이 시작되다가 어떤 짧은 루프(#1) 안에 갖히게된다 그부분에서 [F12]를 눌러서 해당 루프를 자세히 봐야한다

.

 

루프를 돌려보면 ECX는 회전마다 1씩감소하고 EDX와 EDI는 1씩 증가하는걸 볼 수있다. EDX에서 한바이트를 읽어서 EDI에 쓰고 있는 중이다. (ctrl+F8을 돌려 살펴보라!)

 

010153E6에 Bp를 걸고 루프를 탈출한 뒤 다시 트레이싱을 실행해보자.

그러다보면 2번째 커다란 루프를 만날 수 있다.

 

#2. decoding 루프.

-> 압축 해제 루프

두 번째 섹션 주소에서 차례대로 값을 읽어 첫 번째 섹션으로 값을 옮겨 써주는 작업 중...

ESI가 가르키는 두 번째 섹션(UPX1)의 주소에서 차례대로 값을 읽어서 적절한 연산을 거쳐 압축을 해제하며 EDI가 가리키는 첫 번째 섹션(UPX0)에 주소에 값을 써주는 과정입니다.

 

...

...

 

* AL(EAX)에는 압축해제된 데이터, EDI는 첫 번째 섹션의 주소

 

=> al은 1바이트라 inc 1씩 증가시켜 다음 주소를 가르키고 eax는 4바이트라서 add로 4바이트 증가시킨 경우이다.

뭔지 몰랐다능 ... 까묵

NULl이었던 UPX0 영역(01007000)에 데이터가 채워진 모습

그렇게 두 번째 루프를 지나기 위해 01015402에 BP를 걸고 다음 트레이싱을 진행합니다.

바로 밑에서 세 번째 루프를 발견할 수 있습니다.

이 부분은 원본 코드의 CALL/JMP 명령어의 주소를 복원시켜주는 코드라고 합니다. 그냥 알고 넘어가면 대나...

jne는 not equal, cmp 비교시 같지않으면 ZF는 0을 반환합니다.

 

이제 IAT 셋팅만 하면 UPX 압축해제 코드가 끝이나게 됩니다. 다시 트레이싱을 해봅시다.

마지막 루프 입니다! 이 부분이 IAT를 셋팅하는 루프입니다. 01015436 주소에서 EDI=01014000으로 세팅되며, 이곳은 두번째 섹션(UPX1) 영역입니다. 이곳에 원본 notepad.exe에서 사용되는 API 이름 문자열이 저장되어 있습니다.

 

 

 

'Reversing' 카테고리의 다른 글

리버싱 9  (0) 2019.04.10
리버싱 8  (0) 2019.04.09
리버싱 6  (2) 2019.04.04
PE file(3)  (0) 2019.04.03
PE File(2)  (0) 2019.04.03

주소 : los.rubiya.kr

3번째 문제 - goblin 이다.

싱글쿼터 ' 가 치환되어지고 있는게 보인다.

마지막줄을 보아하니.

if($result['id'] == 'admin') solve("goblin");

id값이 admin인것으로 로그인하면... 문제가 풀리는것 같다!

하지만 id='guest'로 고정되어있어서 뭔가 막혔다.

 

일단 no에 0,1,2 등을 대입해보니

no=1에서만 guest가 출력되고 나머지에서는 오류가 반환되지 않는다 그렇다면 !

해당 쿼리에서 빨간 네모박스 부분을 거짓으로 만들고 뒤가 참인 쿼리를 붙여주면 될듯 하다. 바로 실행해보자.

싱글쿼터를 입력하지 않아서 그런지 admin값이 파라미터로 넘어가지 않는거같다. 싱글쿼터를 입력하면 No Quotes~_~문구가 뜬다. 그러면 admin의 아스키 코드값을 넘겨주도록 한다.

다음과 같이 앞의 쿼리는 거짓으로 만들고 id값에 admin의 ascii 값 0x61646D696E를 넘겨주어 Clear를 하였다.

 

GOBLIN CLEAR!!

'Lord of SQLinjection' 카테고리의 다른 글

Lord of SQLinjection - cobolt  (0) 2019.04.02
Lord of SQLinjection - gremlin  (0) 2019.03.27

+ Recent posts