34
Hacker Debugging Uncovered Chapter 9:Hashing and How to Overcome it Chapter 10:Popular Protection Mechanisms Used in Demo Versions 2008.3.10 이이이

2008.3.10 이동현

  • Upload
    hila

  • View
    45

  • Download
    0

Embed Size (px)

DESCRIPTION

Hacker Debugging Uncovered Chapter 9:Hashing and How to Overcome it Chapter 10:Popular Protection Mechanisms Used in Demo Versions. 2008.3.10 이동현. Chapter 9: Hashing and How to Overcome it. Intent. 1980 년대 후반 복잡한 패스워드 암호화 에 대한 응용프로그램 개발자의 첫 번째 시도 . 그러나 최신의 디버거와 디스어셈블러로 무장한 크래커 들에겐 불충분 .  - PowerPoint PPT Presentation

Citation preview

Page 1: 2008.3.10 이동현

Hacker Debugging UncoveredChapter 9:Hashing and How to Overcome itChapter 10:Popular Protection Mechanisms Used in Demo Versions

Hacker Debugging UncoveredChapter 9:Hashing and How to Overcome itChapter 10:Popular Protection Mechanisms Used in Demo Versions2008.3.10이동현

Page 2: 2008.3.10 이동현

Chapter 9: Hashing and How to Overcome itChapter 9: Hashing and How to Overcome it

Page 3: 2008.3.10 이동현

IntentIntent

1980 년대 후반 복잡한 패스워드 암호화 에 대한 응용프로그램 개발자의 첫 번째 시도 .그러나 최신의 디버거와 디스어셈블러로 무장한 크래커 들에겐 불충분 . 해시함수의 사용 시도 조차 불충분 .

크래커들은 유효한 패스워드 입력을 위해 실제 패스워드를 찾는 대신 결과 해쉬값을 취함 .   Listing 9.1. The evolution of protection mechanisms if ((s==ch) != "KPNC")           cout << "password fail" << endl;   //Old variant if (hashe(&pasw[0]) != 0x77)     cout << "password fail" << endl;   //New variant 둘 다 하나의 조건 분기를 변경 함으로서 충분하다 .( 크랙 가능 )

Page 4: 2008.3.10 이동현

부실한 보호 메커니즘의 이해부실한 보호 메커니즘의 이해보안 개발자들의 부주의함을 이해하기 위해서 이들을 크랙 해보자 .모순되게도 , 대부분의 프로그램들이 이런 순진한 방식으로 보호가 되어있다 . 왜 프로그래머들은 좋은 의도를 가진 해커들의 조언을 듣고 자신의 실수를 고치려고 하지 않는지 참 수수께끼다 . 잘 디자인 되고 구현된 보호 메커니즘은 비용이 많이 든다 . 그리고 잠재적 고객의 구입을 증가시키지도 않는다 . 어떠한 보호 메커니즘도 뚫린다 . 유명하면 유명할수록 더 빠르게 . 

Page 5: 2008.3.10 이동현

Crack02.exeCrack02.exe

기존방법으로 스트링을 찾아보자 .. 안 보인다 ..음 ..  좀더 자세히 살펴보면 .. 리소스 안에 위치하고 있군 .. 그렇다면 LoadString 로 스트링을 불러왔겠군 . 

crack02.exe 를 dependency 로 추적 . 음 ? 이놈이 LoadString 를 임포트 하지 않네 ? 의존하는 dll 을을 추적해보자 .. CString 가 호출하는군 .. 음 MFC42.dll  의 임포트 테이블을 덤프 해보니 심볼은 없고 Ordinal 만 있다 .

맵 파일을 참고하자 . MFC42.map LoadStringA 의 주소로 툴을 이용해서 가보자 . 코드의 생김이 함수 호출과 비슷하다 . 자 이주소 0x5F404042 - 0x5F400000(loaded address) = 0x4042 ( map 파일 확인 .. )

모든 것은 IDA-Pro 를 이용함으로써 쉽게 해결 . 이로서 Protection mechanism 의 시작지점을 찾았다 .

마지막 점프 지점을 무조건 점프 명령으로 교체함으로써 손쉽게 Crack 되었다 . 

Page 6: 2008.3.10 이동현

Crack03.exeCrack03.exe

Crack02 는 너무나 쉽게 뚫린다 .( 단지 한 바이트의 수정으로 ) 이 Protection Mechanism 을 개선 해보자 .패스워드를 프로그램 자체내부에 암호화 해서 내장한다 . 툴을 이용해서 실행파일에 암호화된 패스워드를 저장하는 것도 가능하지만 직접 소스 코드에 암호화된 패스워드를 넣자 . 

Page 7: 2008.3.10 이동현

Crack03.exe 계속Crack03.exe 계속

마지막 jz 를 무조건 분기로 교체 .결과적으로 어떤 패스워드를 넣던지 프로그램은 받아 들인다 .그러나 정상적으로 동작하지 않음 .

Page 8: 2008.3.10 이동현

Crack03.exe 계속Crack03.exe 계속입력된 패스워드가 사용되는 곳에 집중하자 .401291 번지가 핵심

SecretString[pTxt++] = SecretString[pTxt] ^ Password[pPsw++];

Page 9: 2008.3.10 이동현

Crack03.exe - 계속Crack03.exe - 계속 SecretString[pTxt++] = SecretString[pTxt] ^ Password[pPsw++];잘 알려진 Vernam cipher 이다 .소스 참고

if (mult(hashe(&pasw[0]),hashe(&pasw[0]))!=504) s0.LoadString(IDS_WRONG);이 암호 체크 로직을 분석해 내야 한다 .

Page 10: 2008.3.10 이동현

Chapter 10:Popular Protection Mechanisms Used in Demo Versions

Chapter 10:Popular Protection Mechanisms Used in Demo Versions

Page 11: 2008.3.10 이동현

어떤 것들 ?어떤 것들 ?

Limiting the FunctionalityLimiting the Term of UseLimiting the Number of StartupsThe Nag ScreenThe Key File

Page 12: 2008.3.10 이동현

Limiting the FunctionalityLimiting the Functionality

Cracking the program that requires registration doesn’t cause any difficulties.The demon version VS fully functional version.

Physically missing.Cracking is impossible.

Reconstruction of the missing code?You should study the algorithm of interaction between the remaining and the missing code.

Usually the required code is physically present but never gains control.

Page 13: 2008.3.10 이동현

Crack0d.exeCrack0d.exe

아주 간단한 시도프로그램 제작 시 리소스 편집기에서 활성화 옵션을 비활성화 한 경우리소스 편집기로 해당 exe 파일을 열어 해당 컨터롤 활성화 .

Page 14: 2008.3.10 이동현

Crack0e.exeCrack0e.exe

Crack01 보다 까다로운 경우 .컨터롤의 활성화 여부와 상관없이 내부 플래그를 이용해서 등록 여부를 검증 .

외부에서 리소스 편집기로 컨터롤만 활성화 시키는 걸로는 정상적인 동작을 수행할 수 없다 .

리소스 편집기로 컨터롤 활성화 불가능 .프로그램 시작 시 API 를 이용한 비 활성화 .Customizer 등으로 활성화 시도 후 아래 절차 시도 .

Page 15: 2008.3.10 이동현

Crack0e.exe - 계속Crack0e.exe - 계속

시도1. “This is an illegal.. “ 메시지 검색 .2. 프로그램을 제어하는 변수를 찾는다 .

Esi 는 클래스의 인스턴스이고 , 원하는 변수도 같은 방법으로 초기화 .컴파일러의 최적화 등의 경우 아주 어려운 작업이나 , 많은 경우 효과적이다 . Esi +

3. 제어 변수를 찾아서 수정 후 수행 .성공 !!60

4. 어떤 보호 알고리즘의 분석 없이 한 바이트의 수정만으로 Crack 성공 .기존의 보호 알고리즘 등은 모두 정상적으로 동작한다 .

5. 광범위하게 알려지고 사용되어지는 방법 .6. 엄청난 양의 코드를 분석하고 회피를 위해 점프하는 등의 기법에 비해 훨씬

쉽다 .

Page 16: 2008.3.10 이동현

Crack0f.exeCrack0f.exe

Crack0e 예제의 경우 하나의 제어 변수만 존재 했었다 .그러나 이러한 제어변수가 여러 개로 구성되고 , return SomeResult*(!FlagReg1 ^ FlagReg2); 와 같은 로직으로 체크가 된다면 기존의 시도는 실패한다 .다행히 프로그래머들은 게을러서 이러한 바이트들을 신중하게 관리하지 않는다 .

Page 17: 2008.3.10 이동현

Crack0f.exe - 계속Crack0f.exe - 계속

1. 첫번째 시도 .1. EnableWindow 를 찾는다 .2. 두군 데의 컨터롤 변수를 수정한다 .3. 버튼은 활성화 되었으나 정상 동작하지 않음 .

2. 또 다른 원인이 어딘가 존재한다 .3. 다행히 컴파일러는 이런 조각들은 가까이 배치하는 경향이 있다 . –

이는 Cracker 의 일을 줄여준다 .1. 주위의 다른 변수의 값을 변경해 보았다 .2. 빙고 ~ . 제대로 동작하는 결과 출력 .3. 보안 알고리즘은 세 개의 플래그를 사용하는 로직 이었다 .

• S0.SetAt(0, s0[0]*(!RegFlag_1^RegFlag_3));

• 제 4, 5 의 제어 변수가 없다고 어떻게 장담하는가 ?• 보통 제어 변수는 전역 변수이고 , 잘 설계된 OOP 언어에서는 이런 변수는

거의 없다 .• 모든 건 개발자가 게으르다는 데 있다 .

Page 18: 2008.3.10 이동현

Crack10.exeCrack10.exe

존재하는 기능을 막아둔 프로그램의 Crack 은 상대적으로 쉽다 .이전과는 달리 demo 버전의 프로그램에서는 특정 기능의 코드가 물리적으로 존재하지 않을 때 어떻게 하는가 ?또한 컴파일러는 사용되지 않는 코드는 제거해 버린다 .결국 최종 실행파일에 해당 기능의 코드가 존재할 가능성은 없다 .보안개발자가 행복해지고 , Cracker 가 불행해 지는 순간이다 .그러나 이 프로그램의 경우 해당 텍스트 버퍼에 접근이 가능하다면 새로운 기능을 추가 하는건 어렵지 않다 .

BOOL CCRACK10Doc::OnSaveDocument(LPCTSTR lpszPathName) {

// TODO: Add your specialized code here and/or call the base classAfxMessageBox("This is a limited version. Please purchase fully functional one");return 0;

// AfxMessageBox("OK");

// return CDocument::OnSaveDocument(lpszPathName);

}

Page 19: 2008.3.10 이동현

Crack10.exe - 계속Crack10.exe - 계속

문제점PE 파일에 새로 작성한 코드를 삽입하는 일은 아주 어렵다 .이전에 축적된 DOS 와 이전 Windows 에서의 지식은 쓸모가 없다 .그러나 , Windows 는 DLL 을 통한 코드의 수정이라는 방법이 있다 .

고려 사항들 .프로그램에 Import 된 함수들을 탐색 할 수 있어야 한다 . – IDA 의 rdata 섹션 .새로운 코드를 파일에 삽입해야 한다 .

다행히도 실행파일 (DLL) 내에는 충분한 공간들이 존재 .컴파일러는 최적화를 통해서 함수 경계에 0x10 바이트의 경계를 둠 .

원하는 함수를 호출하기 위해선 GetProcAddress 함수가 필요 .이 함수가 import 되어 있지 않기 때문에 Import table 의 수정이 필요하다 .

Import table 의 수정 .컴파일러는 일반적으로 PE 파일 내에 많은 여유공간을 만든다 . – 결국 추가 코드 삽입이 어렵지 않음 .이를 위해 PE file Format 의 숙지 필요 .

Page 20: 2008.3.10 이동현

Crack10.exe - 계속Crack10.exe - 계속

1. Import section 을 찾는다 .2. Import section 의 구조 . – 참고 1, 참고 2

1. 이 section 의 첫번째 데이터는 IMAGE_IMPORT_DESCRIPTER 의 배열 .2. 첫 두 바이트는 RVA 에 대한 포인터 .(IMAGE_THUNK_DATA)3. .. 좀더 자세한 내용은 참고를 참고 .

3. 툴을 이용하면 쉽게 진행할 수 있지만 , 이러한 과정을 손으로 해보자 .1. 해커는 결국 그들의 머리와 손에 의존한다 . 결국 이런 스킬 들이 필요하다 .2. PEKPNXE by Kris Kaspersky.

4. PE file format 의 학습 .1. http://hdp.null2root.org/reversing/PE_analysis_anesra.pdf2. http://en.wikipedia.org/wiki/Portable_Executable

Page 21: 2008.3.10 이동현

Limiting the Term of UseLimiting the Term of Use

많이 쓰이는 데모 버전 용 제한 기법총 실행 횟수 제한 .정해진 기간 동안만 동작 .

레지스트리나 외부 파일에 정보를 저장할 필요가 있다 .여러 가지 시도들 .레지스트리 수정 .시스템 시간 변경 .시간 시간의 수정 .

Page 22: 2008.3.10 이동현

Crack05.exeCrack05.exe

처음 실행 후 20 일 동안 유효하다 .재 설치는 전혀 도움이 되지 않는다 .첫 수행 시간은 어디에 기록 될까 ?레지스트리 ?

이는 레지스트리 모니터 툴을 이용해서 쉽게 확인이 가능하다 .Sysinternals 의 Regmon 사용 .Vista 는 Process monitor 사용 .

레지스트리를 수정 하는건 불편하다 .

Log 를 통한 Protection mechanism 의 분석 .1. 먼저 HKEY_CURRENT_USER\SOFTWARE\CRACK05 라는 이름의 레지스트리

키를 찾는다 .2. 만약 키가 존재 하지 않는다면 이 키를 생성하고 현재 시간을 세팅 한다 .3. 키가 존재한다면 , 현재 시간과 처음 실행된 시간을 비교해서 수행 여부를

결정한다 .

Page 23: 2008.3.10 이동현

Crack05.exe - 계속Crack05.exe - 계속

프로그램이 항상 처음 수행된 효과가 나도록 코드를 수정한다 .IDA 를 이용 RegCreateKeyExA 를 호출하는 곳을 찾는다 .리턴 값을 비교하는 곳을 찾아서 Jnz 명령을 nop 두개로 교체 .

LONG WINAPI RegCreateKeyEx( … ); Return Value

If the function succeeds, the return value is ERROR_SUCCESS.If the function fails, the return value is a nonzero error code defined in Winerror.h. You can use the FormatMessage function with the FORMAT_MESSAGE_FROM_SYSTEM flag to get a generic description of the error.

IDA-pro 를 이용한 disassemble 결과 그래프의 분기 관찰 .

Page 24: 2008.3.10 이동현

Crack06.exeCrack06.exe

레지스트리가 아닌 파일에 저장 될 때Filemon 을 사용 로그를 분석해서 어떤 파일을 사용하는지 파악 한다 .Vista 의 경우 process monitor앞 예제와 비슷한 코스로 Crack 시도 .

Page 25: 2008.3.10 이동현

Limiting the Number of StartupsLimiting the Number of Startups

앞 예에서와 마찬가지로 카운터를 저장할 필요가 있음 .Filemon, regmon 의 로그를 통해서 Protection algorithm 분석일반적인 응용프로그램은 수많은 레지스트리 키를 생성한다 . 이중 어떤 것인 카운터 인가 ?만능열쇠는 없다 .연속적 프로그램 실행의 결과 log 를 통해서 변경되는 부분을 발견할 수 있다 .( 카운터가 증가 되거나 )

Page 26: 2008.3.10 이동현

Crack09.exeCrack09.exe

카운터를 찾기가 힘들다 .변경되는 데이터가 어떤 때는 증가되고 , 어떤 때는 감소 되는등 임의적이다 .진실을 밝히기 위해 debugger 와 disassembler 를 동원한다 .IDA-pro 를 통한 분석 .

aCount1 의 이름을 찾고 ,xRef 로 참조 하는 곳으로 이동 .Dec 부분을 nop 로 교체 .

RegQueryValueEx(hKey,"Count1",0,&TYPE,(LPBYTE) &Count1,&res);RegQueryValueEx(hKey,"Count2",0,&TYPE,(LPBYTE) &Count2,&res);

Count2 = Count2 ^ Count1;Count2--;printf("Count %x \n",Count2);if (!Count2) return 0;

srand((unsigned)time( NULL ) );Count1 = (unsigned) rand();Count2 = Count2 ^ Count1;

RegSetValueEx(hKey,"Count1",0,REG_DWORD,(CONST BYTE *) &Count1,4);RegSetValueEx(hKey,"Count2",0,REG_DWORD,(CONST BYTE *) &Count2,4);

Page 27: 2008.3.10 이동현

The Nag ScreenThe Nag Screen

프로그램 중간 중간에 등록을 하란 메시지 박스로 귀찮게 함 .지속적인 귀찮음 유발로 정식 제품을 구매하도록 유도 .광고 등을 출력 하기도 한다 .Nag screen 을 보고 참고 사용하거나 , 정식 구매자가 되거나 사용자의 선택이다 .그러나 대부분의 사용자는 비용을 지불하기를 꺼린다 .

이는 구매력이 없어서라기 보다는 정신적인 문제이다 .

Cracker 의 입장에선 이는 Protection mechanism 이 아니다 .Nag screen 이 뜨지 않도록 코드를 수정하는 것은 어렵지 않다 .두 가지 일반적 방법 .

Key generator 의 사용 .Nag screen 을 표시하는 코드의 수정 .후자는 권장하지 않는다 . 전자가 쉽고 심플하다 .

Page 28: 2008.3.10 이동현

Crack0b.exeCrack0b.exe

프로그램 수행 중 주기적으로 표시되는 nag screen.이때는 모든 기능 정지 .첫 번째 시도 .

dialog 를 표시하는 부분의 코드를 수정 .어떻게 이 부분을 찾을 것인가 ?Dialog 를 생성하는 부분에 breakpoint 를 잡는 방법은 적절치 않다 .

MFC42.dll 내부에서 일어나는 일이라 ..

Cdialog::DoModal 을 시도하자 .Domodal 의 ordinal 은 0x9d2Breakpoint to mfc42!ORD 09D2저자는 제대로 breakpoint 를 잡기 위해서 12 시간 소모 .

Page 29: 2008.3.10 이동현

Crack0b.exe - 계속Crack0b.exe - 계속

Dialog::domodal 를 호출하는 코드를 수정 하는 건 무식한 방법 .위 함수를 호출하게 되는 조건을 처리하는 분기 문을 무력화 시킨다 .원하는 대로 동작한다 .끝인가 ?

Cracker 들은 호기심이 많다 .당신이 진정한 cracker 이라면 내부 protection mechanism 이 어떻게 동작하고 있는지 관심을 가져야 한다 .

Page 30: 2008.3.10 이동현

Crack0b.exe - 계속Crack0b.exe - 계속

좀더 관찰 후 프로그램이 SetTimer 로 타이머를 생성후매 타이머 이벤트 마다 다이얼로그를 생성한다 .SetTimer 호출을 무력화 시킨다 .함수 호출 뿐만 아니라 스택 관련 코드도 같이 수정 .

그냥 타이머의 시간을 아주 큰 수로 설정해서 통과를 시켜 보았다 .

Page 31: 2008.3.10 이동현

Crack0c.exeCrack0c.exe

시간과 상관없이 생성되는 nag screen.Spyxx 등으로 살펴봐도 WM_TIMER 메시지는 발생하지 않는다 .메시지 프로세싱 루프에서 현재 시간을 체크하거나 , 독립된 쓰레드에서 전담해서 시간을 체크 .일반적으로 후자의 방법을 많이 사용 .VC++ 의 process viewer 를 이용해서 관찰 .시간 체크 전용 쓰레드의 루프 코드를 무력화 .HKEY_CURRENT_USER\Software\crack0c\Regit 의 생성으로 한방에

Page 32: 2008.3.10 이동현

The Key FileThe Key File

가장 이상적인 방법 .두 가지의 접근 방법 .새로운 유효 키 파일의 생성 .Protection mechanism 을 무력화 시키는 코드 수정 .일반적으로 첫 번째 방법 선호 .

일반적으로 key 파일은 유져 이름과 등록 번호가 저장된다 .혹은 물리적으로 빠진 코드를 이 key 파일에 넣기도 한다 .

이건 정말 쉽고도 크래킹을 현실적으로 불가능하게 만드는 방법이다 .여기서 불가능 하다는 말은 정식 제품을 구입하는 비용보다 크랙에 들어가는 비용이 더 크다는 의미 이다 .

Page 33: 2008.3.10 이동현

Crack11.exeCrack11.exe

File 의 존재 여부로 체크 .Disassempler 로 확인 .findFirstFileA 를 호출하는 부분 발견 .File monitor 로 확인 .단순히 파일의 존재 여부 뿐 아니라 , 생성 시간 , 파일 사이즈 등을 비교할 가능성 있음 .FindFirstFile 함수는 해당 함수의 존재 여부 뿐만 아니라 _WIN32_FIND_DATA 의 정보도 리턴한다 .

typedef struct _WIN32_FIND_DATA {DWORD dwFileAttributes;FILETIME ftCreationTime;FILETIME ftLastAccessTime;FILETIME ftLastWriteTime;DWORD nFileSizeHigh;DWORD nFileSizeLow;DWORD dwReserved0;DWORD dwReserved1;TCHAR cFileName[MAX_PATH];TCHAR cAlternateFileName[14]; } WIN32_FIND_DATA, *PWIN32_FIND_DATA, *LPWIN32_FIND_DATA;

Page 34: 2008.3.10 이동현

Crack11.exe - 계속Crack11.exe - 계속실제 Protection mechanism 을 분석 전체 알고리즘을 무력화 시키는 부분은 아주 많은 assembly 언어대한 스킬이 필요 .쉬운 접근 방법 시도 .IDA-Pro 의 disassemple 결과를 확인 하면 파일을 찾은 후 분기 하는 부분을 확인 .이 분기를 강제로 성공한 코드 영역으로 점프 하도록 코드를 수정 .