Software Security (2)

임정환·2023년 6월 8일
0

실행파일은 결국 기계어의 집합이다. 이를 해당 아키텍쳐에 대응하는, 어셈블리어로 1대1 매핑할 수 있다. 공격자는 디스어셈블을 통해, 프로그램의 로직을 확인하고 공격할 수 있다.
지금부터 공격자는 오로지 실행파일만 가지고 있다고 가정한다.

리버스 엔지니어링

  • 리버스 엔지니어링 Tool
    • 디스어셈블러 : 정적분석
    • 디버거 : 동적분석
    • 에디터 : 실행파일을 수정

리버스 엔지니어링 예제


시리얼 넘버를 입력해서, 유효한지 검증하는 소프트웨어 실행 파일이 존재한다.

디스어셈블을 통해 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로 매핑된다면 역으로 기계어를 어셈블리어로 바꿀 수 있기 때문이다. 하지만, 공격자를 조금 짜증나게는 해볼 수 있다.

  • 안티-디스어셈블
    역어셈블 자체를 힘들게 한다. 예를 들자면, 소스코드를 암호화하는 것을 생각해 볼 수 있다.
  • 안티-디버깅
    동적 분석을 힘들게 할 수 있다. 디버거의 경우, 멀티 쓰레드나 파이프라인에 취약하다. MIPS 아키텍쳐를 예로 들자면, CPU는 명령어를 FEMW의 4단계로 나누고 pre-fetch한다. 즉, 명령어를 미리 미리 가져온다는 뜻이다.

    CPU는 명령어 1~4를 미리 가져와서 파이프라인으로 처리할 것이다.
    만일 명령어 1이 명령어 4를 Dead code로 만드는 명령어라고 생각해보자.
    어차피 CPU에는 명령어 1~4가 적재되어 파이프라이닝을 통해 실행중이므로 명령어 1에의해 명령어 4가 변화되어도 CPU에 올라와있는 원래의 명령어 4를 실행하므로 괜찮다.

    하지만 디버거의 경우, 명령어를 순차적으로 실행하므로 명령어 1을 실행하면 명령어 4가 junk명령어로 오버라이트 되고 명령어 4를 실행할 차례가 되면 fault가 발생할 것이다.
  • 변조방지 ( Tamper - resistance )
    Guard라고도 불리며 Code의 일부를 hash하여 파일 변조 여부를 확인한다. 너무 티나게 해시값이 존재할 경우, 공격자가 해당 해시값을 삭제할 수 있기에 잘 숨기는 것이 중요하다.
  • 코드 난독화 ( Obfuscation )
    일부러 코드를 난독화 한다. 사람이 읽기 좋은 코드를 만드는 것이, 좋은 소프트웨어이지만 일부러 그 반대로 난독화된 코드를 삽입하여 공격자가 정적 분석을 어렵게 만든다.

소프트웨어 복제

만일 취약점이 있는 소프트웨어를 배포했다고 생각해보자. 한번 소프트웨어가 크래킹 되면, 모든 소프트웨어가 크래킹당하게 되는 상황에 처할 수 있다. ( BOBE : Break Once Break Everywhere )
어떻게 대처할 수 있을까?

  • Metamorphic Software
    Malware뿐만 아니라 일반적인 소프트웨어에서도 보안을 위해 Metamorphic하게 소프트웨어를 디자인할 수 있다. 하지만, 소프트웨어가 일종의 파편화가 되므로 버전 업그레이드가 어려울 수 있다.

DRM

Digital Right Management. 배포된 디지털 자산을, 지속적으로 통제하기 위한 방법이다. 여러 방법이 있겠지만, 기본적으로 코드를 암호화하는 방법이 있다.

하지만, 소프트웨어 속에 key가 존재하기 때문에 공격자는 key를 RE을 통해 탈취 가능하다. 결국, 'key를 어떻게 숨기는가?'가 제일 중요한 쟁점이 될 것이다.
물론 아무리 소프트웨어적으로 잘 디자인해도, 직접 카메라로 녹화를 하는 방법등은 막을 수 없지만...

PDF DRM


PDF의 DRM을 위해 서버와 클라이언트 소프트웨어가 존재한다.

보호된 pdf를 보기 위해 key를 서버에 요청하고, 해당 key를 가지고 클라이언트 소프트웨어를 통해 복호화할 수 있다. 클라이언트 소프트웨어를 RE으로부터 막기 위해 어떠한 기법이 적용됬을까?

기본적으로 변조 방지기법과 난독화가 적용되었다.
난독화를 통해 정적 분석을 어렵게 하며
변조 방지를 통해 동적 분석을 어렵게하는 구조이다. 다른 PDF DRM 기법으로는 아래와 같은 기법이 존재한다.

  • 워터 마크
  • 안티 - 스크린 캡쳐

스트리밍 미디어 DRM

Netflix를 시청하는데, 중간에서 공격자가 평문 바이트 스트림을 탈취한다면? 아마, 해당 동영상이 바로 넘어가게 될 것이다. 이를 방지하기 위해, 스크램블링 알고리즘을 사용한다.

먼저 클라이언트가, 자신의 Client 소프트웨어 하단에 baked된 스크램블 알고리즘 리스트를 송신한다. 서버는, m번째 알고리즘을 사용하겠다고 선언하고 해당 m으로 암호화된 바이트 스트림을 전송한다. 스크램블 알고리즘은 Client에 의해 읽을 수 없게 되어있어 List가 탈취되어도 안전하다. 만일, 특정 스크램블 알고리즘이 파훼된다면 서버가 다른 알고리즘을 선택하면 그만이므로 유연성이 증가한다는 장점이 있다.

안전한 Software 개발

현재 많은 기업들이, 보안을 신경쓰지 않는 Penetrate and Patch 모델을 채택하고 있다. 빠르게 소프트웨어를 개발해서, 시장을 선점하는게 중요하므로 보안 이슈가 발생하면 그때 그때 패치를 하는 방법이다.

  • 계속 Patch를 진행하면 결국 안전한 SW가 되는가?
    Nope, 결국 patch로 인해 새로운 취약점이 발생한다. 결국, 처음부터 안전한 디자인을 가진 SW를 개발하는 것이 중요하다.

오픈 소스 VS 클로즈 소스

  • 오픈 소스
    소스코드가 다 공개되어있지만, 그만큼 감시하는 눈도 많다는 보안상의 장점 존재
  • 클로즈 소스
    소스코드가 비공개이지만 결국 은폐에 의한 보안 ( 즉, 언젠가는 알려질 수 있다)이다. 각종 알파,베타 테스팅을 통해 테스팅 부족을 보완한다.

결국 오픈소스이든 클로즈 소스이든 보안상의 취약점은 동일하다.
결론은, penetrate and patch 모델에서 탈피하여 안전한 SW를 디자인하고 충분한 Testing이 필요하다는 점이다.

  • 디자인 단계의, 안전한 SW 디자인
  • 구현 이후, 충분한 Testing

결론

어떠한 방식으로든, 완벽한 보안은 존재할 수 없다. 단, 10줄짜리 코드도 그 누구도
bug가 존재하지 않는다고 단언할 수 없다.
그렇기에, 최대한 risk를 minimize하고 안전한 SW를 디자인하고 충분한 Test이후 배포하는 것이 중요하다.

profile
CS 박제

0개의 댓글

관련 채용 정보