실행파일은 결국 기계어의 집합이다. 이를 해당 아키텍쳐에 대응하는, 어셈블리어로 1대1 매핑할 수 있다. 공격자는 디스어셈블을 통해, 프로그램의 로직을 확인하고 공격할 수 있다.
지금부터 공격자는 오로지 실행파일만 가지고 있다고 가정한다.
시리얼 넘버를 입력해서, 유효한지 검증하는 소프트웨어 실행 파일이 존재한다.
디스어셈블을 통해 test eax,eax 의 결과에 따라 시리얼 넘버가 맞는지 아닌지 분기한다. test가 0을 반환할 경우 True, 아니면 False
test는 eax와 eax를 bitwise and를 실행한다. 따라서, eax가 0일 경우에만 결과값이 0이되고 True를 반환한다. 로직을 생각해보자면 아마, eax는 '원래 시리얼' - '사용자 입력 시리얼' 정도가 될 것이다. 사용자 입력값이 정답이라면 eax는 0이 되고 True가 된다.
이제 해당 test를 bitwise XOR로 치환하게 되면, eax가 어떠한 결과가 나오든 항상 그 결과는 0이다 ( 배타적 논리합 XOR는 두 bit가 달라야지 1을 반환하기 때문)
Hex 기계어로 변환시 85 C0가 test eax,eax이므로 실행파일의 85를 XOR와 대응하는 33으로 치환하면 xor가 된다.
실제로 실행파일을 위조하게되면, 이후에는 어떠한 시리얼 번호를 입력하여도 통과가 되는 것을 볼 수 있다.
사실 배포된 소프트웨어를 역어셈블하는 것을 막을 수 있는 수단은 없다. 어차피, 실팽파일은 기계어의 집합이고 기계어와 어셈블리어가 1대1로 매핑된다면 역으로 기계어를 어셈블리어로 바꿀 수 있기 때문이다. 하지만, 공격자를 조금 짜증나게는 해볼 수 있다.
만일 취약점이 있는 소프트웨어를 배포했다고 생각해보자. 한번 소프트웨어가 크래킹 되면, 모든 소프트웨어가 크래킹당하게 되는 상황에 처할 수 있다. ( BOBE : Break Once Break Everywhere )
어떻게 대처할 수 있을까?
Digital Right Management. 배포된 디지털 자산을, 지속적으로 통제하기 위한 방법이다. 여러 방법이 있겠지만, 기본적으로 코드를 암호화하는 방법이 있다.
하지만, 소프트웨어 속에 key가 존재하기 때문에 공격자는 key를 RE을 통해 탈취 가능하다. 결국, 'key를 어떻게 숨기는가?'가 제일 중요한 쟁점이 될 것이다.
물론 아무리 소프트웨어적으로 잘 디자인해도, 직접 카메라로 녹화를 하는 방법등은 막을 수 없지만...
PDF의 DRM을 위해 서버와 클라이언트 소프트웨어가 존재한다.
보호된 pdf를 보기 위해 key를 서버에 요청하고, 해당 key를 가지고 클라이언트 소프트웨어를 통해 복호화할 수 있다. 클라이언트 소프트웨어를 RE으로부터 막기 위해 어떠한 기법이 적용됬을까?
기본적으로 변조 방지기법과 난독화가 적용되었다.
난독화를 통해 정적 분석을 어렵게 하며
변조 방지를 통해 동적 분석을 어렵게하는 구조이다. 다른 PDF DRM 기법으로는 아래와 같은 기법이 존재한다.
Netflix를 시청하는데, 중간에서 공격자가 평문 바이트 스트림을 탈취한다면? 아마, 해당 동영상이 바로 넘어가게 될 것이다. 이를 방지하기 위해, 스크램블링 알고리즘을 사용한다.
먼저 클라이언트가, 자신의 Client 소프트웨어 하단에 baked된 스크램블 알고리즘 리스트를 송신한다. 서버는, m번째 알고리즘을 사용하겠다고 선언하고 해당 m으로 암호화된 바이트 스트림을 전송한다. 스크램블 알고리즘은 Client에 의해 읽을 수 없게 되어있어 List가 탈취되어도 안전하다. 만일, 특정 스크램블 알고리즘이 파훼된다면 서버가 다른 알고리즘을 선택하면 그만이므로 유연성이 증가한다는 장점이 있다.
현재 많은 기업들이, 보안을 신경쓰지 않는 Penetrate and Patch 모델을 채택하고 있다. 빠르게 소프트웨어를 개발해서, 시장을 선점하는게 중요하므로 보안 이슈가 발생하면 그때 그때 패치를 하는 방법이다.
결국 오픈소스이든 클로즈 소스이든 보안상의 취약점은 동일하다.
결론은, penetrate and patch 모델에서 탈피하여 안전한 SW를 디자인하고 충분한 Testing이 필요하다는 점이다.
어떠한 방식으로든, 완벽한 보안은 존재할 수 없다. 단, 10줄짜리 코드도 그 누구도
bug가 존재하지 않는다고 단언할 수 없다.
그렇기에, 최대한 risk를 minimize하고 안전한 SW를 디자인하고 충분한 Test이후 배포하는 것이 중요하다.