본문 바로가기

Game Programming

dnspy를 이용한 디컴파일 삽질

일의 시작은 갑작스런 큰 업무의 의뢰였다.

해당 업무를 진행하기에는 5~6개월 가량 예상되는 문제가 있어서 git을 뒤지게 되는데...

있었지만 일부 기능이 제한되었다. 되는데 못하게 막아두었으니 제한된 것이 맞을 것이다.

물론 리플렉션 처리 후 일일히 뜯어다 써도 되지만...

이런 식으로 하면 일단 필드 명칭 얻어다 왔다리 갔다리 해야 해서 제일 피하고 싶은 방식이었지만...

그래서  dnspy를 통해 dll을 뜯기로 했다.

dnspy는 ilspy 코어를 활용하여 만들어진 디컴파일러로서 edit기능까지 갖춘 매우 훌륭한 도구이다.

그래서 했는데.. 역시 무료라서...

해당 dll에 난독화 ctl코드가 적용되어 있다. 이렇게 stx, etx계열의 컨트롤 코드가 사용되면 일반 texteditor에서는 컴파일이 불가능해진다. utf8기반의 ide가 가지는 단점 중 하나인데..물론 이것도 해결 방법은 있지만 쉬운 길은 아니다..우선 최대한 쉽게 가기 위해서 컨트롤 코드를 제거하기로 했다.

똑같은 rid를 가지는 vpr정보를 토대로 타입 분류키를 추가했다.

cls는 클래서 st는 구조체 en은 이넘타입등...문제가 c#은 클래스가 포괄적이라 enum, struct 모두 클래스로 본다. 그 안에서 value타입이면 enum과 struct고 이 안에서 enum타입을 별도로 두기 때문에 분류가 조금 복잡하게 이루어진다.

암튼 진행해서 보니 어이쿠...지금 수정된 화면에는 안나오지만 난독화시 내부 sealed 클래스 안에 상위와 같은 name을 줄 수 있는 옵션이 있는데 그것도 적용되었다. 역시 오랜세월 개발을 하신 교수님의 dll답다. 빈틈이 없네.

거기다 가상계열의 경우 하부에서 상부로 모두 리스팅해서 다시 네이밍 해야 하는 문제가 있었다. 컴파일된 바이너리와 달리 디컴파일된 소스코드는 단지 텍스트라서 rid, mdtoken과 같은 직렬화가 불가능하기 때문에 무조건 네이밍을 맞추어야 하는 것이다. 그런데 추상 a의 추상 함수가 상속된 b의 경우 a의 추상 함수와 다른 네이밍이면 어떻할까? 맞추면 된다. 여기까진 쉽지만 어...클래스 명과 함수명이 같네? 이런...메타 정보에 이런식이면 상속된 클래스는 해당 부모의 정보를 일단 리스팅 하고 해당 리스팅 된 정보를 2차 pass에서 별도 네이밍 처리해야 한다. 한마디로 디컴파일 과정이 매우 복잡해진다.

어쩌지..이거 또 커지는데..이러면 원래 목적과 달리지니까 매우 흔들렸다.

결론은 소스코드 출력해보고 선택하자는 맘에 프로젝트를 익스포트했다.

그렇다 교수님의 승리다. 그냥 인젝션하는 편이 더 편할 것으로 판단되어 1안으로 돌아가기로 했다.

2박 3일동안 많은 기술을 구경할 수 있던 것이 소득이라면 소득이었다. 코드 난독화는 하는 둥 마는 둥 하는 편이었는데 진정한 il기반 난독화 기술의 핵심을 본 것 같았다. 기존에는 왠만하면 뜯어낼 수 있었기 때문에 더욱 기대했는데 무참하게 꺾였다. 어차피 우물안 개구리인 것이다. 좌절보다는 즐거운 퍼즐을 푸는 듯한 시간이었지만 이제 남은 것은 지루한 노가다 뿐일지도 모른다. 그래도 직접 만드는 것보다는 빠를테니 말이다.

 

오늘 날도 삽질은 즐겁다.