'분류 전체보기'에 해당되는 글 18건

  1. 2017.02.22 170222
  2. 2016.11.25 ㅁ1
  3. 2016.11.10 Reversing.kr-Easy_KeygenMe 풀이
  4. 2016.11.08 리버싱 패턴-0
Security/뭐했니2017. 2. 22. 02:42

버퍼 오버플로우 방지기법들


stack canary : 


GCC에서 SSP(stack-smashing protector) 기능에서 사용된다.

스택 return 주소 앞에 랜덤한 정수(canary)를 기록해 둬서, 그 수가 변경되었음을 체크하는 방식이다.

GCC SSP 기능에서는 canary는 난수+문자열 종결값("\n","\0", -1 같은 값들) 의 형태로 되어 있어서

문자열 덮어쓰기는 불가능함. 카나리값은 각 task_struct에 별도로 저장된다(task마다 다른 값)



메모리디버거 : 메모리 할당/해재 등을 감시. GC에서 필요로 함


실행 가능 공간 보호 : 특정 메모리 공간에서의 실행을 불가능하게 함. NX비트라는 기술 이용

CPU기술


UAF 취약점 : malloc()이 어떻게 돌아가는지

완전 기본적인 코드만 작성하고 끝남


Return to libc 공격 : ret을 libc에 있는 함수(시스템콜?)주소로 바꿔서 권한 따기


배열 초기화(?) 


어떤분이 열심히 작성해둔 글을 읽음. 컴파일러 공부의 필요성을 느낌(...)


함수 프롤로그, 에필로그


프롤로그 : 스택 프레임 포인터생성(호출한 함수의 프레임포인터 저장), 공간창출,

 사용할 범용 레지스터 백업(실행상태 보존)

에필로그 : 위에꺼 거꾸로...

레지스터 실행상태 복구, 스택복구, 프레임포인터 복구.


함수의 프롤로그 단계를 건너뛸 때, 함수 주소에 얼마를 더해주면(+3?) 됨. BOF나 다른 공격기법에

사용되지 않을까


64bit 체제에서는 __fastcall 이 아니여도 파라미터를 레지스터로 전달한다고 한다

옛날 자료들만 봐와서 64bit는 잘 모름. 역시 공부를..



PLT와 GOT : 리눅스에서는 동적 라이브러리 방식을 사용할땐 이렇게 함.

윈도우 PE의 IAT랑 비슷한 역할을 하는거같음. 자세한건 나중에 더..




vm 키기 너무 귀찮음..

맥이 있었으면..

살껄

'Security > 뭐했니' 카테고리의 다른 글

toc-tou (time of check to time of use) - 1  (0) 2017.05.30
20170305  (0) 2017.03.05
20170302..3  (0) 2017.03.03
20170301..2  (0) 2017.03.02
ㅁㅇㅇ 170223  (0) 2017.02.23
Posted by Palette14
2016. 11. 25. 17:19

기초가 중요함..

그렇다고 너무 오랫동안 기초만 하는건 좀 아닌거같음

어느정도 지나면 다음단계로 넘어가야되는데

넘어가야되는데..


'' 카테고리의 다른 글

번역된 글에 대해  (0) 2017.05.30
Posted by Palette14
Security/Reversing2016. 11. 10. 19:41

Reversing.kr - Easy_KeygenMe 풀기





/*


진짜 초보라 설명에 오류가 있거나

틀린 점이 있을수 있습니다..ㅠㅠ

열심히 공부해서 고쳐갈게요


*/


파일을 다운로드 하고 압축을 풀면 ReadME.txt파일이 있다. 내용은 다음과 같다.

Serial이 5B134977135E7D13일 때의 Name을 알아내라


구해야 하는 값을 알게 되었다.

프로그램 실행 시, 콘솔 창이 뜨면서, Name을 입력받고, Serial을 입력한다. 그리고 알맞은 값을 입력했나 판별한다.

문제 해결을 위해선 Name과 Serial의 관계를 알아야 한다.


일단 Ollydbg로 디버깅하자.


Ollydbg로 파일을 실행하고, 마우스 오른쪽 클릭 후 search for -> all referenced string메뉴로 들어가서

Serial Number를 입력하라는 문자열을 스택에 넣는 코드로 가본다

그러면 Serial Number와 Name의 관계를 찾을 수 있지 않을까?


Name 과 Serial Number는 분명히 어떠한 관계 속에 있고, 그 관계를 검증하는 방법을 알아내야 한다

(중간과정 생략)

.

.

.




명령어에서 Serial Number를 저장하고 있는 [ESP+10]의 주소와 의문의 문자열 [ESP+74] 주소를 레지스터에 넣어 반복문으로 같은지 비교하고 있다. 같고 다름에 따라 함수 호출을 위해 스택에 넣는 문자열이 달라진다.

아마 이 함수가 맞는 값을 입력했는지 알려주는 함수임에 틀림없다(breakpoint 잡고 직접 해보길 바래ㅁ)

같으면 "Correct!" 문자열을 출력하고, 같지 않으면 "Wrong" 문자열을 출력한다.


아마도 ESP+74에 있는 문자열은 입력한 Name이 재료가 되는 Serial Keygen 방식으로 만들어진 문자열일 것이다.


 


.

그럼 일단 Serial Keygen에 필요한 재료인 Name을 입력받는 곳으로 가보자.

00401059에 있는 CALL 004011A2이 Name을 입력받는 함수고 호출하고, 호출인자로 넣은 주소인 ESP+10가

입력받은 문자열을 저장할 부분이 될 것 같다.


이후엔 저장된 문자열의 길이를 구한다. >> 자주보이는 리버싱 패턴

만약 문자열 길이가 0이면 반복이 끝난 지점으로 보내버린다. 아마 문자열 입력받는 코드로 다시 가는 등

프로그램이 알아서 처리할것이다.


반복문(Keygen routine)


0040107C부터 보이는 루프가 Serial Keygen 루틴일 것이다

처음에는 ESI의 값이 3보다 크면, 값을 0으로 만들어버린다. 분명 무슨 역할을 할 것이다.


위 조건문을 통과하면, ECX에는 스택상에 있는 특정 값을 넣는다. 그런데 이때 ESI가 주소값에 영향을 준다. 

EDX에는 아까 입력한 Name값의 주소를 넣어준다.

근데 여기에도 EBP값이 이에 영향을 미치게 된다(EBP를 변수처럼 사용. BASE POINTER아님)

아마 각각의 문자에 접근하려고 할 것 같다.

그러면, ECX에 들어갈 값, ESI+ESP+0C엔 뭐가 들어있을까...?


바이트 단위로 0x10, 0x20, 0x30 값이 차례로 들어 있다. 그뒤엔 아까 입력한 Name이 저장되어 있다.

반복문의 조금 뒤쪽을 보면, 반복할때 마다 ESI를 1 증가시켜주는 코드가 있다(004010AC)

ESI가 3 보다 크면 값을 0으로 만들어 준다는 내용과 종합해 보면, ECX에 들어가는 값은 차례대로 0x10, 0x20, 0x30뿐이고, 0x30값 후엔 다시 0x10값을 갖게 된다.


EDX에 넣은, Name값의 주소인 EBP+ESP+10도 마찬가지로, 뒤에 반복할때 마다 EBP가 1씩 증가하는 코드가 있다(004010A2)

즉, EDX의 값은 문자열의 인덱스와 같은 역할을 할 것이다.

.

.

.

그 뒤에는 XOR이 나온다.

첫 반복때엔 Name 맨 첫번째 값 0000 0041(16)과 0000 0010(16)값을 xor연산하여 ECX에 넣어둔다.


후에 함수가 하나 호출되는데, 매개변수를 보고 한번 맞춰보자 ㅎㅎ


스택에는 나중에 입력받을 Serial number와 비교하는 문자열인 ESP+74의 주소를 넣는다.

그 후, "%s%02X" 문자열 주소를 스택에 또 넣고 ESP+7C 주소도 넣는다. 이렇게 스택에 값을 넣어두고, 함수를 호출한다.


그러면 함수 매개변수가 전달되는 꼴은 " 함수명( ESP+7C , "%s%02x"문자열주소, dest주소, xor된 hex값) " 이렇게 될 것이다.

특정 주소에 문자열을 쓰는 함수이라는 것을 짐작할 수 있고, 아마 C언어의 sprintf 함수일 것이다.


아래는 sprintf함수의 원형이다

int sprintf (char *s, const char *template, ...)


sprintf함수의 첫번쨰 매개변수는 문자열 데이터를 쓸 주소

두번쨰 매개변수는 쓸 문자열(형식문자 포함)

나머지 가변 매개변수는 형식문자에 대응하는 변수들이다.


위처럼 하게 되면, 아마 반복될때마다 원래의 문자열은 %s로 유지되고, xor된 hex값이 2자리로 쓰여질 것이다.

즉 끝에다가 이번에 XOR한 값을 추가해준다.

문자열 길이를 구해 ECX에 넣고, 위에서 Name문자열의 순차적으로 증가하는 인덱스 역할을 할 EBP가 그보다 작으면 반복을 돈다.

아래는 Name을 ABCD로, 반복문을 다 돈 후의 ESP+7C주소의 dump

이렇게 값이 들어간다.


Serial Key 생성 루틴


반복문에서, 0x10, 0x20, 0x30값을 차례로 갖으며, 0x30값을 가진 후에는 다시 0x10값을 갖는 변수가 있다.

그리고, Name문자열을 스캔해서 차례대로 값을 갖는 변수가 있다.

변수는 문자의 ASCII 디코딩 값을 갖는다.


그렇다면, XOR역연산으로 우리에게 주어진 Serial Number값을 이에 해당하는 Name 값으로 바꾸면 된다



파이썬을 잘 못해서 대충 역연산을 해보니 저런 hex값이 나왔다. 저걸 ASCII코드로 encoding하면 된다. 



Name : K3yg3nm3


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


파이썬이 정말 좋은데 함수나 모듈에 대해 너무 모르는거같다ASCII변환.. 

공부해서 더 잘해졌으면 좋겠다 ㅎㅎ

그런데, 비교하는 루틴에 넣는 주소는 ESP+74고, 만들어진 Serial Key 주소는 ESP+7C이다..??


  









'Security > Reversing' 카테고리의 다른 글

RE.kr Twist  (0) 2018.01.09
pwnable.kr 문제  (1) 2017.03.08
리버싱 패턴-0  (0) 2016.11.08
Posted by Palette14
Security/Reversing2016. 11. 8. 20:03

XOR EAX, EAX

OR ECX, FFFFFFFF


// EDI에 처리를 원하는 문자열의 주소 넣음


REPNE SCAS BYTE PTR ES:[EDI]

NOT ECX


하면 문자열의 길이가 ECX에 구해진다


이유

REPNE 명령어는 Repeat Not Equal을 뜻하는 명령어다. 여기선 ECX 레지스터를 반복 횟수로써 사용한다.

Not Equal 인즉, Equal 상태엔 1로 설정되는 ZF는 0이고 반복 횟수로 쓰는 ECX는 0보다 큰 상태가 유지되야 반복을 계속한다.

명령어가 시행되면 ECX값을 1씩 빼가면서 반복하며, SCAS(SCan A String) 명령어로 EAX와 비교를 한다. 이때 명시된 BYTE단위로 비교하기 때문에 EAX의 8bit 부분인 AL값과 EDI가 가리키는 문자열의 모든 문자를 차례차례 비교한다.


EAX를 0000 0000으로 초기화시켰으므로, 문자열의 끝인 널 문자를 만나면 ZF가 1이 되며 Repeat을 멈춘다.

그 후에, ECX값을 비트 반전(NOT) 시키면 반복한 횟수가 나타난다(깎은 횟수). 즉, EDI가 가리키는 문자열의 길이가 나온다.


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



문자열 관련 함수(비교, 붙이기)에서 많이 등장할거 같음

ASCII가 아닌 다른 인코딩에서는 비교 단위가 BYTE가 아닐거 같음(굳이..)



'Security > Reversing' 카테고리의 다른 글

RE.kr Twist  (0) 2018.01.09
pwnable.kr 문제  (1) 2017.03.08
Reversing.kr-Easy_KeygenMe 풀이  (0) 2016.11.10
Posted by Palette14