Monday, July 6, 2009

간만의 삽질기 - 가내수공업으로 크랙하기

아주 간간히 시간 때우기로 흥미로워 보이는 논문들을 인쇄해서 읽거나 모니터로 스르륵 읽는데, 읽고 나면 잃어 버리기 십상입니다. 다운로드 폴더에 pdf파일들이 쌓여 있다가 모르고 지워버리면 다 날아가버리는 일도 흔하고. 그래서 Paper라는 프로그램 (http://mekentosj.com/papers/)을 한동안 사용했는데 매우 좋습니다. 학교 안이 아니라서 ACM이나 IEEE같은 repository에 바로 접근 못하는 점은 좀 아쉽긴 하지만, 구글 스칼라에서 논문 매치해주고 정리해주는 기능은 특히 훌륭합니다. 뭐 리뷰는 다음에 시간나면 자세히 올리기로 하고, 아무튼.

이 프로그램은 30일 체험버전을 제공해 주고 있습니다. 나중에 박사 가면 하나 사줄 생각인데, 음... 뭐 지금은 가난한 학생이니 일단은 날짜 제한을 돌아가보고자 약간의 삽질한 것을 기록으로 남겨보고자 합니다. (그래야 나중에 패치되도....다시.....-.-)

방법

1. 일단은 gdb로 바이너리를 까봅시다.
gdb --annotate=3 /Applications/Papers.app/Contents/MacOS/Papers

2. 심볼들을 보고 어디를 살펴 봐야할지 감을 잡아 봅니다.

info functions

오호라, 이런 놈이 있군요
...
0x0000e3d8 -[AppDelegate hasExpired]
...

브레이크포인트 걸고 프로그램을 몇 번 돌려보니, 정품인지 확인 하는 길목 마다 호출 되는 것 같네요. 얘를 잘 패스 시켜주면 되는가 봅니다.

3. hasExpired를 디스어셈블 해봅시다
Dump of assembler code for function -[AppDelegate hasExpired]:
0x0000e3d8 <-[AppDelegate hasExpired]+0>: mov 0x1e0040,%eax
0x0000e3dd <-[AppDelegate hasExpired]+5>: push %ebp
0x0000e3de <-[AppDelegate hasExpired]+6>: mov %esp,%ebp
0x0000e3e0 <-[AppDelegate hasExpired]+8>: cmpb $0x0,(%eax)
0x0000e3e3 <-[AppDelegate hasExpired]+11>: je 0xe3f4 <-[AppDelegate hasExpired]+28>
0x0000e3e5 <-[AppDelegate hasExpired]+13>: mov 0x1e008c,%eax
0x0000e3ea <-[AppDelegate hasExpired]+18>: mov $0x1,%edx
0x0000e3ef <-[AppDelegate hasExpired]+23>: cmpb $0x0,(%eax)
0x0000e3f2 <-[AppDelegate hasExpired]+26>: je 0xe3f6 <-[AppDelegate hasExpired]+30>
0x0000e3f4 <-[AppDelegate hasExpired]+28>: xor %edx,%edx
0x0000e3f6 <-[AppDelegate hasExpired]+30>: leave
0x0000e3f7 <-[AppDelegate hasExpired]+31>: mov %edx,%eax
0x0000e3f9 <-[AppDelegate hasExpired]+33>: ret

요렇게 생겼는데, 대충 보면 저 처음 나오는 cmpb에서 뭔가 체크를 할 것 같은 느낌이 강하게 옵니다. 몇 번 돌려보고 경험적으로(-_-) 정품이 아니면 +11줄의 je 어쩌고에서 걸리지 않고 +13줄로 넘어간다는 사실을 파악합니다. 그래서 저 je를 jmp로 바꿔주면, 마치 인증 받은 것 처럼 동작하겠구나 라는 사실을 간파할 수 있습니다.

4. 바이너리를 까서 저 인스트럭션을 슬쩍 바꿔줍니다.
만일을 위해 /Applications/Papers.app/Contents/MacOS/Papers 이 바이너리를 일단 백업해놓습니다. 아래부터 작업 경로는 /Applications/Papers.app/Contents/MacOS/이라고 가정합시다. file 이나 otool -f 로 바이너리 헤더를 보면 ppc와 i386바이너리가 다 포함된 것을 알 수 있는데, 이 유니버셜 바이너리를 i386용만 분리해 냅시다.
lipo -thin i386 Papers -o Papers.i386

5. Papers.i386 에서 어디를 고쳐야 될지 계산합니다. otool -l로 섹션과 세그멘트 정보를 조회해보면, 코드 섹션들이 메모리에 로드될 시작 위치(addr)와 바이너리에서의 오프셋(offset)이 보입니다. __text섹션의 __TEXT세그먼트를 보면 되는데,
Section
sectname __text
segname __TEXT
addr 0x000023d8
size 0x0019bf7f
offset 5080
align 2^2 (4)
reloff 0
nreloc 0
flags 0x80000400
reserved1 0
reserved2 0

요렇게 생겼습니다. 즉, addr 은 0x000023d8, offset은 5080. GDB에서 본 고쳐야하는 코드는 아래 위치 (0x0000e3e3)이니까,
0x0000e3e3 <-[AppDelegate hasExpired]+11>: je 0xe3f4 <-[AppDelegate hasExpired]+28>

해당 인스트럭션의 바이너리 파일에서의 위치는
offset + ( 0x0000e3e3 - base_addr(==0x000023d8)) 입니다.
계산해보면 0x0000d3e3 (hex계산기 역할을 해준 파이썬 감사를..) 이군요.

6. 바꿀 옵코드 알아내기
다행히도 이 경우에는 인스트럭션 길이가 똑같아서 삽질을 하지 않을 수 있습니다. 인텔 옵코드의 경우 Intel Architecture Software Developer's Manual, Volume 2: Instruction Set Reference Manual 여기 참조. je를 jmp로 바꿔야되는데, 참고로 short je는 74, short jmp는 eb.

7. 바이너리 수정
xxd papers.i386 > papers.i386.hex
텍스트로 고칠 수 있게 아스키 형태로 만듭니다. papers.i386.hex에서 고칠 위치(0x0000d3e3)를 찾아서 74->eb로 수정 (*-_-*)합니다. 끝이 다가오는 군요.

8. 다시 유니버셜 바이너리로 합체
xxd -r papers.i386.hex papers.i386.patched
lipo -replace i386 papers.i386.patched Papers -o Papers.patched

이러면 새 Papers.patched 바이너리가 생성되고 끝! 원래 파일을 잘 바꿔주면 됩니다.

후기
하도 전산과 공돌이 삽질을 안한지 오래 되서 공부도 할 겸 해봤는데, 나름 재미있었네요. 페이징, 세그멘테이션 등 OS들었던 것들 약간 다시 살펴보는 계기가 되기도 했고, 이전에 리눅스 바이너리에 대한 것만 배워서, 일반적으로 이런 건가 했던 것들이 맥OS에서는 다르게 생긴 부분들(ELF가 아니었다니...)을 알게 된 것도 흥미로운 경험이었습니다. ethnic diversity를 체험했다고나 할까요.

제일 삽질한 부분은, 실제로 바이너리에서 옵코드 찾아 고치는 부분이었습다. 머나먼 옛날 SP 과목 수강한 이후로 처음 해보는 지라 반신반의 하면서 고치고 있는데, 당연히 여기 있겠지 한 인스트럭션이 있어야 할 곳이 0000000000000000000.. 이었습니다. 멍하니 한동안 패닉 상태에 빠졌는데, 왜 그런가 하고 생각을 해보니 Universal Binary 때문이더군요. 바이너리를 아키텍쳐별로 뼈와 살을 분리해야되는데, 그걸 하지 않은 것이 문제였습니다. ( otool 이 뼈와 살을 분리하지 않은 유니버셜 바이너리에 대해서는, 해당 머신의 아키텍쳐로 정보를 보여줍니다. 그래서 별 생각 없이 UB를 통째로 열었다가 멍 때리고 있었던 것이었습니다. 나중에서야 otool의 man page를 보니 기본적으로 해당 머신의 아키텍쳐에 해당하는 섹션의 정보를 보여준다고 하더군요 )

참고문서들입니다.


후기1. 블로거로 코드 들어간 글 쓰기 힘들군요.
후기2. Mekentosj 형님들께 몇 유로 빚을 졌으니 박사 들어가면 갚아야겠습니다. (__)

Monday, June 15, 2009

취리히 여행 사진

20090604 Zurich

누르면 앨범으로..

# 덧1.
피카사에 사진 캡션 붙이는 기능이 있네.
힘들게 따로 글 쓸 필요 없이 그냥 캡션에 써야 겠다 앞으로.
슬라이드 쇼도 처음 봤는데 좋군.

블로그가 날아갔다.

http://blog.cubegem.net
여기에 블로그를 000webhosts.com 이라는 공짜 호스팅을 이용해서 돌리고 있었는데,
며칠 접속을 안 해줬더니 inactivity 때문에 중단시킨다고 날려버렸다.

아 내가 나름 열심히 공들여 쓴 글들도 있었는데 화나네.
공짜 서비스라고 저렇게 막 날려버려도 되는건가.

워드프레스 디비 백업 받아 놓은 게 있긴한데, 다시 워드프레스 설치할 공간이 없기도 하고.
좀 귀찮기도 하고. 시간 나면 살려봐야겠다.

그냥 이제 방황하지 말고 믿을만한 블로거를 써야겠다.