간단하게 정적 분석은 프로그램을 실행하지 않은 상태에서 소스 코드나 컴파일된 코드를 이용해 프로그램을 분석하는 방법이며, 동적 분석은 프로그램을 실제 환경이나 가상 환경에서 실행해 보면서 분석하는 방법이다.
정적 분석은 소스 코드의 모든 부분을 확인할 수 있지만, 실행 환경에서의 상태를 정확히 알 수 없기 때문에 실행할 때에만 알 수 있는 데이터가 필요한 경우 정확히 분석할 수 없다.
반대로 동적 분석은 실제로 실행해 보면서 분석하기 때문에 실행 환경에서의 상태를 잘 알 수 있지만, 프로그램을 실행할 수 있는 환경을 구축하기 어려울 때가 많고 소스 코드의 모든 부분을 테스트해 보기 힘들다는 문제가 있다.
이렇게 각 분석 방식은 장단점이 존재하기 때문에 정적 분석은 주로 개발 단계에서 소스 코드의 구조적인 문제나 실수를 찾아내는 데 사용하며 동적 분석은 테스트나 모니터링할 때 사용한다.
정적 분석(Static analysis) 동적 분석(Dynamic analysis)
분석 대상 | 소스 코드 또는 컴파일된 코드 | 프로그램 실행 환경 |
테스트 범위 | 소스 코드의 모든 부분 | 실행 가능한 경로 |
활용 | 코드 상의 문제나 실수를 찾음 | 테스트, 모니터 |
정적 분석은 에러가 발생하지 않는 코드를 기본적인 상태라고 가정하고, 이 코드를 특정한 가이드라인을 가지고 면밀히 조사하고 분석하는 과정을 말한다.
이러한 기준에 의해서 찾아진 코드를 결함 또는 Code Smell 이라고 한다.
정적 분석 도구로는 CHeckstyle, Cppcheck, PMD, SonarQube, StyleCop, cobertura, cpplint 등이 있으나 SonarQube가 가장 많이 사용된다.
Jenkins와 같은 CI/CD 툴과의 연계도 가능함.
정적 분석
장점
1. 프로그램의 전체 구조를 파악하기 쉽다.
- 프로그램이 어떤 함수로 구성됐고 함수들은 서로 어떤 호출 관계를 갖는지, 어떤 API를 사용하고 어떤 문자열을 포함하는지 등을 종합적으로 볼 수 있다.
2. 분석 환경의 제약에서 비교적 자유롭다.
- 실행을 전제로 하는 동적 분석을 윈도우 환경에서 apk를 대상으로 하기는 다소 번거롭다. 그러나 정적 분석은 적절한 도구만 갖춘다면 시도할 수 있다.
3. 바이러스와 같은 악성 프로그램의 위협으로부터 안전하다.
- 동적 분석의 경우 바이러스를 실제로 실행해야 하므로 감염될 우려가 있지만 정적 분석은 프로그램을 실행하지 않고 분석하므로 이런 걱정을 하지 않아도 된다.
단점
1. 난독화(Obfuscation)가 적용되면 분석이 매우 어려워진다.
- 최근 많은 개발자가 자신의 소프트웨어를 리버싱으로부터 보호하기 위해 난독화 기법을 사용한다. 난독화가 적용되면 실행 흐름을 파악하기가 어려워진다.
2. 다양한 동적 요소를 고려하기 어렵다.
- 프로그램은 실행 중 영향을 주고 받는 여러 함수로 구성되기 때문에 어떤 함수가 특정 시점에 정확히 어떤 인자와 어떤 전역 변수를 가지고 실행될지는 정적으로 알기 어렵다.
동적 분석은 소스 코드 자체를 분석하는 것이 아닌, 일련의 시나리오를 적용하여 실행하는 과정에서 문제가 발생하지 않는지 확인하는 방식이다.
개발자가 개발 과정에서 진행하는 입력값에 대한 유효성 검사, 디버깅, 유닛테스트 등도 일종의 동적 분석이다.
시스템 오픈 전 일부러 부하를 주어서 문제점을 파악하는 스트레스 테스트도 동적 분석이다.
소스코드를 실행시키며 프로그램 내 결함 및 취약점 분석, 메모리 및 스레드 결함 등을 분석할 수 있는 도구로 Avalanche, Valgrind 등이 있다.
동적 분석
장점
1. 코드를 자세히 분석해보지 않고도 프로그램의 개략적인 동작을 파악할 수 있다.
- 어떤 입력에 대한 개별 함수 또는 프로그램의 출력을 빠르게 확인할 수 있으므로, 이 출력값들을 기반으로 동작을 추론해 볼 수 있다.
단점
1. 분석 환경을 구축하기 어려울 수 있다.
프로그램을 실행하지 못하면 동적 분석을 진행할 수 없다. 다른 환경의 프로그램을 동적 분석할 때에는 가상 머신을 구축하거나 프로그램을 실행할 수 있는 장치를 구매해야 하는데, 이 과정이 대상에 따라 매우 번거롭고 어려울 수 있다.
2. 또한, 동적 분석의 일종인 디버깅을 방해하는 안티디버깅(Anti Debugging)이 있다.
Ex) 아래의 코드처럼 자신이 디버깅 당하고 있는지 검사하고, 디버깅 중이면 프로그램을 강제로 종료시키는 방법이 있다.
if (is_debugging()) // 디버깅인지 확인
exit(-1); // 프로그램 종료
Func();