알림!
이 글은 국방망 내 대한민국 해군 1함대 지휘통신대대 자유게시판에 게시한 내용을 베껴 적은 뒤 오타 및 비문만 수정한 글입니다. 실제 작성일은 2022년 3월 4일입니다.
필승! 불철주야 당직근무로 고생하시는 전국의 수병님들, 오늘도 안전항해를 기원합니다. 저번에 파워쉘로 이것저것 만들다가 대형사고를 터뜨리고 자중하고 있는 674기 참치입니다. (덕분에 컴퓨터를 포맷당해서 구포탈에서 연재하던 레이트레이싱 관련 내용이 전부 날아갔습니다…)
이번에 휴가를 다녀왔습니다. 오미크론을 회피하기 위해 온갖 이상한 짓을 다 했더니 이게 휴가를 갔다온건지 뭔지 잘 모르겠습니다. 하지만 휴가에서 복귀한 저를 기다리고 있었던 건 입항 날짜가 정해지지 않은 죽음의 항해 뿐… 아, 휴가 딱 한 차수만 늦게 나갈걸…
아무튼 한동안 이것저것 바빠서 이곳에 못 들어왔는데 신포탈로 이전하고 나니 이럴 수가! WYSIWYG HTML 편집기가 생겨있었습니다. 이게 바로 문명의 진보라고 하는 건가 싶어 감격스럽기 그지없습니다. 아쉽게도 HTML 직접 편집은 불가능한 모양입니다만…
여하튼 신포탈로 옮겨온 김에, 레이트레이싱 관련 작업도 복구할 시간도 벌어야겠다, 흑마법에 관한 이야기를 써 보려고 합니다.
보통 프로그래밍을 할 때 흑마법이라고 하면 아래 둘 중 하나를 이야기합니다.
- 기반 시스템의 설계자가 의도한 방식과는 다른 방법으로 문제를 해결하거나,
- 기반 시스템의 구조 자체의 특성을 남용해서 문제를 해결하는 것인데,
전자는 주로 프로그램 익스플로잇 개발에서, 후자는 통상적인 방법으로는 불가능한 최적화 등을 할 때 사용되겠네요.
여기서 기반 시스템이란 프로그래밍 언어의 설계상 허점과 같은 부분부터 컴파일러/링커, 실행 파일 포맷 등과 깊게 들어가면 프로세서의 ISA(Instruction Set Architecture)까지 전부 포함하는 개념입니다. 아마 이 시리즈에서는 후자를 주로 다루겠지만 뭔가 흥미로운 게 보인다면 전자에 관한 이야기도 조금 해보려고 합니다. 글 하나에 알고리즘(흑마법) 하나, 이런 식으로 쓰면 좋지 않을까 싶습니다.
실제로 글을 쓰기 전에, 대충 맛보기로 흑마법의 예시를 보여드리려고 합니다.
마침 레딧에서 예전에 코멘트를 달았던 게시글을 발견했는데, 다시 보니 정말 거지같은 신기한 흑마법이라 가져와 봤습니다. 퀴즈 형식이니 흥미가 있으신 분들은 한번 풀어봐 주시기 바랍니다. (문제와 관련 없는 내용은 살짝 바꿔서 원본 코드와 완전히 똑같지는 않습니다만…)
아래는 Windows 환경에서 C++로 작성된 코드로, Visual C++ 컴파일러(cl.exe)를 이용해 빌드될 코드입니다. 런타임은 Visual C++ 2012 Runtime을 사용한다고 가정하겠습니다.
((void(__thiscall*)(Entity*, unsigned int))(*(void***)this)[N])(this, index);
자, 여기서 퀴즈입니다. 이 이상한 코드는 무엇을 하는 코드일까요? 더 나아가 이 코드를 작성한 사람의 의도까지 맞히면 보너스 포인트입니다!
정답을 맞히신 수병님께는 다음에 진해에 가서 충무 복지관의 명물, 자몽 아이스 아메리카노를 선물로 사드리겠습니다. 진해에 안 계신 수병님께는… 음… 어… 뭐가 있지…? 뭔가 보여드리겠습니다.
여하튼, 몇 가지 사항을 힌트로 알려드리겠습니다. (힌트라기보다는 전후 문맥을 알려드리는 거에 가깝습니다만…)
Entity,N,index와 같은 모든 identifier는 이미 정의되어있다고 가정합니다.- 위 코드는 어떤 클래스의 메서드 본문 안에서 발췌했습니다. 편의상 이 메서드를
Mystery::do_something이라고 부르겠습니다. N은 고정된 값을 갖는 상수입니다.const는 아니고,#define또는constexpr로 정의되어 있다고 생각해 주십시오.index는Mystery::do_something에서 접근 가능한 변수입니다. 메서드 매개변수거나 로컬 변수, 인스턴스 멤버일 수도 있습니다.Entity는 가상 클래스이며,Mystery클래스와 어떤 관계를 맺고 있습니다.
그러면 행운을 빕니다!