악성코드 하나를 분석하던 중, 아주 흔하면서도 지금까지 짜증나게 만들었던 루틴이 하나 등장했습니다.

단순하게 LoadLibrary와 GetProcAddress를 통해 모듈 핸들과 함수 주소를 가져오고, 이를 전역변수에 대입하여 다른 코드들에서 사용하는 것으로 IAT에 자신이 사용하는 함수명을 표시하지 않게 하는 흔한 기법이지만, 몇가지 문제점이 있었습니다.



[그림 1. 첫번째 문제]


 첫째, 양이 많았습니다. 한 함수 내에서 40개가 넘어가는 함수들의 주소를 가져오는데, 이는 다음 문제점과 더해 미친듯한 시너지를 발휘합니다.



[그림 2. 두번째 문제]


 둘째, 변수명이 스택에 저장되어있습니다. 바이트 단위로 할당되어있기 때문에 보통이라면 이걸 전부 아스키 문자로 바꿔서 하나하나 읽고 무슨 함수인지를 파악해야 합니다. 함수가 엄청나게 많다 보니 1500바이트가 넘어가는 양입니다.




[그림 3. 세번째 문제]


 셋째, 변수 값이 암호화되어있습니다. 정확히는 0x08이라는 고정된 값으로 XOR되어있는 것이지만, 어쨌든 그냥 봐서는 어떤 함수인지 알기가 힘듭니다. 셋중 하나라도 문제가 없었으면 그냥 복사해서 파이썬 스크립트로 복호화하거나 해서 하나하나 네이밍해줬겠지만, 도저히 그럴 양이 아니었습니다.



 여기에서 잠시 현자타임이 왔고, 이걸 어떻게 해결할까 하다가 지금까지 너무 무식하게 분석해왔다는 생각이 들어서 IDAPython을 이용하여 자동 스크립트를 짜기로 결심했습니다.




[그림 04. 스크립트 동작 전]


 작성한 스크립트를 돌리기 전의 모습입니다. 



[그림 05. 스크립트 로그]


 스크립트를 동작시키면 IDAPython 콘솔창에 로그가 남습니다.




[그림 06. 스크립트 동작 후]


 스크립트를 동작한 후 새로고침해주면 위와 같이 GetProcAddress를 이용하여 대입한 값들이 네이밍됩니다. 예전 BoB 4기에서 잠깐 한 적이 있기는 했는데 사실 기억에는 전혀 남아있지 않아서 혼자 여기저기 검색하면서 조잡하게 짰습니다.


이 스크립트에는 아직 개선할 점이 몇 가지 있습니다.


- GetProcAddress의 결과를 전역변수가 아닌 지역변수나 Struct의 멤버변수같은것에 대입하는 경우는 네이밍이 되지 않습니다.

- 특정 함수 내에 커서를 둔 채로 실행해야 하며, 해당 함수 내에서의 GetProcAddress에 대해서만 네이밍을 진행합니다.

- GetProcAddress함수의 주소를 직접 구해서 RenameGetProcAddrVars 함수에 인자로 넣어야 합니다.


스크립트를 사용하면서 나중에 조금씩 업데이트해갈텐데, 그러면서 하나씩 해결해갈 예정입니다.


소스코드 및 정리한 내용은 아래에 있습니다.


IDAPythonUtils.py




 소스코드 내에서 사용한 idaapi의 함수들은 다음과 같습니다.


※ ea라는 용어는 Effective Address의 약자로, 주소값을 의미합니다.

- Byte : 인자로 ea를 받으며 해당 주소의 1바이트 값을 반환합니다. 리터럴 상수처럼 정적으로 값이 확인 가능해야 합니다.
- GetFunctionAttr : 첫번째 인자로 ea, 두번째 인자로 받아올 함수의 속성을 입력받아 해당 함수의 속성을 가져옵니다. 여기에서는 함수 시작 주소와 끝 주소를 받아오는데에 사용했습니다.
- GetDisasm : 인자로 ea를 받아 해당 주소의 값을 디스어셈블하여 문자열로 리턴합니다.
- GetOpnd : 첫번째 인자로 ea를, 두번째 인자로 가져올 오퍼랜드를 0-Base로 입력받습니다. 디스어셈블된 오퍼랜드 자체를 넘겨줍니다. (예:  lea eax, [esp+674h+var_617]의 경우 :[esp+674h+var_617]: 리턴)
- GetOperandValue : 첫번째 인자로 ea를, 두번째 인자로 가져올 오퍼랜드를 0-Base로 입력받습니다. 오퍼랜드에 넘어간 값을 강제로 int형으로 바꿔서 반환하는 것 같습니다. (예: lea eax, [esp+674h+var_617]의 경우 93 리턴)
- here : 현재 커서가 가리키는 주소 반환
- PrevHead : ea를 인자로 받아 바로 이전 명령의 주소 반환
- NextHead : ea를 인자로 받아 바로 이후 명령의 주소 반환
- XrefsTo : ea를 인자로 받아 해당 주소를 참조하는 주소들을 iterable하게 반환




블로그 이미지

__미니__

E-mail : skyclad0x7b7@gmail.com 나와 계약해서 슈퍼 하-카가 되어 주지 않을래?

댓글을 달아 주세요