themida는 debugger 등을 통해서 application을 reversing해서 application을 Crack 하지 못하도록
application의 실행 code 및 Data들을 난독화하는 프로그램입니다. 제일 유명합니다.
무료 패킹(==난독화) 툴들이 몇가지 있으나 금방 풀려버리나 봅니다. 그리고 themida 로 패킹한 것도 엄청난 능력자님들은 몇일 고생해서 풀어버리는 듯합니다. 자세한 방법은 모릅니다.
구입 >
중간 업체 없는게 더 싸지 않을까 하고 홈페이지 직접 방문해 보고 국내 reseller와 비교 해봤는데,
국내 reseller를 통해서 구입하는게 인터넷 Home page를 통해 결재하는 것보다 2~3 만원 정도 더 싸네요. 리셀러를 통해 사는게 더 싸다는 희안한 현실~
문의 >
site에 접속해서 문의 mail 남기면 보통은 1~2 일안에 답변이 잘 옵니다. 3~4일 후에나 답변온 적이 1번 정도 있었구요. (http://www.oreans-support.com/kmp/index.php?/) Program Files 무설치 형태로 압축해서 주며, 원하는 Folder에 넣고 사용하면 됩니다. 인증관련 아무런 과정도 없어요. 그냥 쓰면 된데요~ ㅋ (왠 자신감?)
UI : Delphi - UI 느낌이 VC++ 은 확실히 아니었죠~
엔진 : ASM - 대단합니다. 이 복잡한 프로그램의 Engine을 우째 어셈블리어로 개발했는지~ ㅠㅠ~ 존경스럽네요.
themida 제품의 UI 입니다.
나라별 언어 pack 같은거 제공해주면 좋을텐데, 그런거 없습니다. 그리고 보시면 UI가 상당히 불편합니다.
packing 할수 있는 파일을 UI 형태로는 1번에 1개 밖에 하지 못합니다. 물론, 나중에 설명드리겠지만 한꺼번에
여러개를 packing 할 수도 있습니다만, UI로 packing 적용할 때에는 1번에 1개밖에 안됩니다. ㅠㅠ.
오늘날 대부분의 상업용 난독 처리기에서는 의미 없는 식별자를 적용하는 이름 바꾸기 기법을 사용합니다. 보통 이러한 식별자는 한 문자 정도로 길이가 짧습니다. 난독 처리기는 코드를 처리할 때 다음 번에 대체할 의미 없는 식별자를 선택합니다. 이름 바꾸기 방법은 겉으로는 간단해 보이지만 되돌릴 수 없다는 점에서 해싱이나 문자 집합 오프셋보다 유용합니다. 프로그램 논리는 유지되지만 이름은 무의미해집니다. 따라서 프로그램 구조를 이해하기가 아주 어려워집니다. a, t.bb(), ct, 2s(e4)와 같은 식별자의 의미를 invoiceID, address.print(), userName, deposit(amount)과 같은 개념으로 유추해 내기는 아주 어렵습니다. 그래도 프로그램 논리는 리버스 엔지니어링할 수 있습니다.
보다 정교한 형태의 난독 처리에는 PreEmptive Solutions에서 고안하여 특허를 받은 알고리즘인 Overload Induction이 사용됩니다. 보통 이름 바꾸기도 여전히 사용되지만 교묘하게 왜곡되기도 합니다. 메서드 식별자는 철저히 범위를 분석한 후에 최대한 오버로드됩니다. Overload Induction은 이전 이름을 각각 하나의 새 이름으로 바꾸는 대신 최대한 많은 메서드의 이름을 동일한 이름으로 바꿉니다. 놀랍게도 이와 같은 복잡한 상황에서도 논리는 손상되지 않습니다. 다음은 Overload Induction 기법의 강력한 기능을 보여 주는 간단한 예입니다.
Dotfuscator의 Overload Induction 기능으로 난독 처리한 후 리버스 엔지니어링된 소스 코드
<pre class="code" style="font-family: Consolas, Courier, monospace; line-height: 17.5499992370605px;">private void a(a b) {
while (b.a()) {
a = b.a(true);
a.a();
a(a);
}
}
이 예에서 난독 처리된 코드가 더 간단하다는 것을 알 수 있습니다. 이름 바꾸기를 수행하면 부수적으로 크기 축소 효과를 얻을 수 있습니다. 예를 들어, 길이가 20자인 이름을 a()로 바꾸면 많은 공간(19자)이 절약됩니다. 문자열 힙 항목을 보존하는 방식으로도 공간이 절약됩니다. 모든 이름을 ?Ba뵹?바꾼다는 것은 ?Ba뵲?한 번만 저장되므로 ?Ba뵹?이름을 바꾼 메서드나 필드가 모두 ?Ba뵺?가리킬 수 있음을 의미합니다. Overload Induction을 사용하면 가장 짧은 식별자가 계속해서 다시 사용되므로 이 효과는 더욱 커집니다. 일반적으로 Overload Induction이 사용된 프로젝트는 메서드 중 최대 70%의 이름을 a()로 바꿉니다.
Dotfuscator는 MSIL 파일을 처리할 때 파일에서 디버그 정보와 중요하지 않은 메타데이터를 제거합니다. 이렇게 하면 보호 및 보안 성능이 향상될 뿐 아니라 MSIL 파일의 크기가 축소됩니다.
난독 처리는 소스 코드가 아닌 컴파일된 MSIL 코드에 적용되는 프로세스입니다. 이름을 바꾸어도 개발 환경과 도구는 변경되지 않으며 소스 코드는 어떠한 방법으로도 변경되거나 읽히지 않습니다. 난독 처리된 MSIL 코드는 기능적으로 기존 MSIL 코드와 동일하며 CLR(공용 언어 런타임)에서 실행할 때 동일한 결과를 나타냅니다. 그러나 반대의 경우는 가능하지 않습니다. 강력하게 난독 처리된 MSIL을 디컴파일할 수 있다고 해도 원본 소스 코드와 비교하면 의미에 상당한 차이가 있습니다. 다음 그림은 Dotfuscator의 난독 처리 과정을 보여 줍니다.
PreEmptive Solutions에서는 Java용 DashO 도구를 필두로 하여 1996년부터 중간 컴파일된 소프트웨어를 보호하고 향상시켜 왔습니다. PreEmptive Solutions의 제품은 강력한 성능과 다양한 기능 및 특허 받은 고유 기능으로 시장을 주도해 왔습니다.
Dotfuscator는 지적 재산의 보호 문제를 염려할 필요 없이 강력한 .NET 플랫폼을 활용할 수 있도록 해주는 일련의 도구로 제공됩니다. Dotfuscator에는 세 가지 버전이 있습니다.
Dotfuscator Community Edition은 무료로 기본적인 난독 처리 기능을 제공하는 버전입니다. 식별자의 이름을 바꿔 리버스 엔지니어링에 대한 차단 수준을 올리는 것이 주 목적입니다. Dotfuscator Community Edition에는 보다 쉽게 보호하는 고급 기술이 사용되었습니다. 또한 의미 없는 임시 식별자로 이름을 바꾸기 때문에 크기가 약간 줄어듭니다.
일반적으로 서버의 SSH 접속하기 위해 사용자의 아이디와 비밀번호가 필요하다. 이 말은 즉슨 대충 ID만 알아도 Brute Force Attack 할 수 있다는 얘기가 된다. 서버 관리자 입장에서 생각해보면 여간 짜증나는 일이 아니다. 로그인이 안 된다 할지라도 해킹이 시도되는 동안 소모되는 서버 자원은 어쩔 것인가 ㄷㄷㄷㄷ
이를 방지하기 위해 Fail2Ban 과 같은 Python 기반의 스크립트를 이용하여 지정된 횟수 이상으로 로그인을 실패하면 해킹으로 판단하여 일정시간 접근을 차단시키는 방법도 있다. 하지만 이 방법도 지정된 횟수 이내로.. 예를 들면 로또보다 더한 확률로 1~2번 시도만에 로그인이 성공하면 낭패다. (그러니 유저들을 추가할 땐 비밀번호 정책을 빡세게 합시다 ㄷㄷㄷ)
하지만 OTP를 이용하게 되면 약간은 안심이 될 것 같다. 1분마다 6자리의 숫자가 갱신이 되고 그 이전의 숫자조합은 무용지물이 되어버리니 이 얼마나 짱짱한가. 몇가지 OTP 서비스들이 있긴 하지만 Google OTP(정확히 말하면 Google Authenticator) 를 이용하기로 했다. 별 거 없다. 왜냐면 구글신이니까..
말머리에서 언급한 바와 같이 SSH 접속하기 위해선 사용자의 아이디와 비밀번호가 필요하지만 Google Authenticator 를 이용하면 그 중간에 OTP 번호를 입력하는 절차가 추가된다.
예를 들면 다음과 같다.
일반적인 SSH 로그인
OTP 이용한 SSH 로그인
세팅하는 방법을 순서대로 나열하겠다. 기존의 타 블로그들에서 작성된 대부분의 Google Authenticator 세팅 방법들은 크게 문제가 없지만 중요한 부분이 빠져있다. 이 글에선 빠지지 않고 모두 작성해놨으니 그대로 차근차근 실행만 한다면 될 것이다.
CentOS 6.8 & 7 기준으로 작성
root (최고관리자) 권한 기준으로 작성
작업시작 전 모든 패키지들을 업데이트 (하지 않아도 크게 상관 없음)
Shell
1
yum-yupdate
.ssh 디렉토리 권한 변경 * 필수 작업 – 0700으로 맞추지 않으면 로그인이 제대로 작동하지 않는다.
OTP(One Time Password)는 '일회용 패스워드'의 일종으로 은행 등에서 사용하는 강력한 인증 방식입니다.
인터넷뱅킹 등에서 보안카드와 OTP 중에서 선택해서 사용할 수 있는 건 이미 많은 사람이 알고 계실 겁니다. 그리고 피싱 사이트들이 보안카드 정보만 빼내가려고 하지 OTP 정보는 아직 건드리려고 시도하지 않기 때문에 수많은 피싱 공격으로부터 안전해진다는 사실도요. 아 이건 잘 모르시려나.
이 포스트는 안전한 은행거래를 위한 가이드가 아니고 OTP를 내 애플리케이션에 사용하는 방법을 설명하는 것이므로 보안카드 얘기는 그만하죠.
구글 OTP, GOTP는 안드로이드나 애플 앱스토어 등에서 다운로드받을 수 있습니다. 찾는 건 알아서 찾으시고, 설치해서 적절히 설정하고 실행하면 이런 화면을 보시게 됩니다.
이 GOTP는 오픈 소스라고 하는데 소스 분석은 나중에 하고요, 이 포스트에서는 이 GOTP를 내 애플리케이션에서 사용하는 방법을 설명드리겠습니다.
여기에는 세 개의 계정이 등록돼있습니다. 마지막 것이 내 애플리케이션에서 사용할 OTP코드인데요, 이걸 추가하는 방법부터 설명드리죠.
메뉴 버튼을 눌러 "계정 설정" 을 선택합니다.
"제공된 키 입력하기" 를 누릅니다. 바코드 스캔을 선택하면 자동으로 카메라가 켜지면서 QR코드를 입력하게 되는데 이 방법은 나중에 별도로 포스팅하겠습니다.
여기에 이렇게 입력을 하는데요, 키 부분은 아무 거나 입력하면 안되고 "애플리케이션 비밀번호"를 사용해야 합니다.
내용추가: secret key는 Base32 인코딩된 10바이트 랜덤 문자열입니다. 관련 포스트는 아래 링크 참조.
보시면 아시겠지만 구글 계정 정보는 입력하지 않습니다. cypu로 시작하는 '애플리케이션 비밀번호'가 일종의 애플리케이션 키 역할을 합니다. 구글 계정하고는 완전히 따로 작동하는 것이기 때문에 설령 여러분이 애플리케이션 비밀번호를 '취소' 해서 키를 삭제한다고 하더라도 이 애플리케이션의 OTP인증은 그대로 동작합니다. 즉 구글 계정과 연동하는 게 아닙니다.
GOTP도 구글 계정하고는 상관없이 작동하는 것이고 애초에 네트워크에 연결돼있을 필요도 없는 애플리케이션입니다. GOTP가 GOTP인 이유는 구글에서 만들었기 때문이지 구글 계정이 있는 사람만 사용할 수 있는것도 아닙니다. 물론 구글 계정이 없는 사람은 저 "애플리케이션 비밀번호"를 다른 방법으로 얻어내야겠죠.
여러 사용자를 회원가입 받아 각각을 otp로 인증하고자 할 때에는 저 secret 부분을 ID와 엮어서 DB에 넣어두면 됩니다. 당연히 secret가 유출되면 해커가 자신의 GOTP에 그걸 등록해서 남의 계정을 막 털어먹을 수 있게 되므로 키관리에 각별히 주의해야 합니다. secret 키를 복호 가능한 암호화를 시켜서 저장하는 등 상상할 수 있는 모든 방법을 동원해서 키 유출을 방지하시기 바랍니다.
참고로 secret는 어떤 특별한 규칙에 따라 생성되는 것으로 보이며 랜덤 문자열을 입력하면 에러를 냅니다. 그래서 구글의 '애플리케이션 비밀번호'를 사용했습니다.
위의 키 관리상의 취약점 때문에 ID와 OTP만 사용하는 인증 방법은 위험하며 패스워드와 병행하여 2단계 인증으로 사용하는 걸 권장합니다.
혹시 뭘 해도 False가 뜨는 사람은 서버 시계(파이썬이 실행중인 컴퓨터의 시계)가 틀린 것이니 NTP등으로 서버 시각을 정확히 맞추시기 바랍니다. 일회용인 ntpdate보다는 항상 시각을 동기화해주는 NTP를 사용하는 것이 좋습니다. 그리고 서버 시계는 로컬 타임이 아니라 UTC에 맞추셔야 한다는거. 서버의 바이오스 타임은 UTC에 맞추고 별도의 타임존 세팅을 통해 로컬 타임을 얻는 게 서버 시각을 설정하는 올바른 방법입니다.
휴대폰은 CDMA프로토콜의 특성상 항상 정확한 시계를 사용하니 휴대폰 시계는 확인할 필요가 없습니다.
혹시 GOTP 앱을 사용하지 않고 자체적인 모바일 클라이언트를 만들려는 분은 위의 onetimepass 모듈의 get_totp() 메서드를 사용하면 됩니다. 이런 식이죠.
>>> otp.get_totp('cypuribxkxbfplde')
981370
>>>
이 get_totp는 매 30초마다 다른 값이 출력됩니다. 마지막 호출 이후 30초가 아니라 매시 매분 25초와 55초 시점에서 갱신됩니다. 따라서 14:35:50에 메서드를 호출했다면 출력 결과가 유효한 시간은 14:35:55까지. 즉 겨우 5초입니다.
간혹 여섯 자리 숫자가 아니라 다섯 자리 이하의 숫자가 뜰 때도 있는데 앞부분이 0이라 그렇게 된 겁니다. 따라서 그냥 사용하지 마시고 꼭 여섯 자리 숫자로 출력될 수 있게 적절한 print 포매팅을 하시기 바랍니다.