원리를 간단히 설명하면 스테가노그래피(Steganography)임.
실행 파일을 포함해서 이미지나 사운드, 동영상 같은 바이너리 파일은 대부분 헤더에 크기 정보를 가지고 있어서
파일 맨 뒤에 어떤 내용을 추가하든 파일 자체의 기능에 전혀 영향을 주지 않는 경우가 많아.
EXE 파일(PE 포맷)도 마찬가지라서 이 프로그램은 그 원리를 이용해서 파일 맨 뒤에 메시지 내용을 써 넣고 시그너쳐를 넣는 방식으로
구현됨 :)
아래는 그 소스 코드. 그냥 프갤에 재미로 올리려고 대충 발코딩으로 짠 거니 코딩 스타일이나 버그 같은 걸로
지적하는 사람은 없길 :p
#include <stdio.h>
#include <windows.h>
#pragma warning(disable: 4996)
#define EXE_FOOTER_SIGNATURE 0xDEADBEEF
typedef struct {
int iMessageLen;
int iSignature;
} EXE_FOOTER, *PEXE_FOOTER;
char *readall(FILE *fp, long *readsize = NULL);
int main(int argc, char *argv[]) {
CHAR szExePath[MAX_PATH];
GetModuleFileNameA(NULL, szExePath, MAX_PATH);
FILE *fp = fopen(szExePath, "rb");
if (!fp) return 1;
EXE_FOOTER foot;
fseek(fp, -8, SEEK_END);
fread(&foot, sizeof(EXE_FOOTER), 1, fp);
if (foot.iSignature == EXE_FOOTER_SIGNATURE) {
fseek(fp, -(8 + foot.iMessageLen), SEEK_END);
char *msg = new char[foot.iMessageLen + 1];
fread(msg, sizeof(char), foot.iMessageLen, fp);
msg[foot.iMessageLen] = '\\0';
printf("Message\\n====================================\\n%s\\n", msg);
getchar();
return 0;
}
if (argc != 3) {
fprintf(stderr, "Message Compiler v1.0\\n\\n"
"Usage: %s <msgfile> <outfile>\\n\\nParameters:\\n"
"\\t<msgfile>: 메시지가 담긴 텍스트 파일(ANSI encoding)을 지정합니다.\\n"
"\\t<outfile>: 빌드된 실행파일이 저장될 파일 이름을 입력합니다.\\n", argv[0]);
return 1;
}
long lEXELen;
char *exe = readall(fp, &lEXELen);
fclose(fp);
FILE *fp_text = fopen(argv[1], "rb");
if (!fp_text) {
fprintf(stderr, "[!] An error occurred while opening file %s!\\n", argv[1]);
return 1;
}
long lTextLen;
char *text = readall(fp_text, &lTextLen);
fclose(fp_text);
FILE *fp_out = fopen(argv[2], "wb");
if (!fp_out) {
fprintf(stderr, "[!] An error occurred while creating file %s!\\n", argv[2]);
return 1;
}
fwrite(exe, sizeof(char), lEXELen, fp_out); // write exe binary
fwrite(text, sizeof(char), lTextLen, fp_out); // write message
foot.iMessageLen = lTextLen;
foot.iSignature = EXE_FOOTER_SIGNATURE;
fwrite(&foot, sizeof foot, 1, fp_out);
fclose(fp_out);
printf("[+] EXE Created!\\n");
return 0;
}
char *readall(FILE *fp, long *readsize) {
fseek(fp, 0, SEEK_END);
long lFileSize = ftell(fp);
if (readsize) *readsize = lFileSize;
fseek(fp, 0, SEEK_SET);
char *arr = new char[lFileSize];
fread(arr, sizeof(char), lFileSize, fp);
return arr;
}
그냥 하이라이팅 없이 올릴게 ㅡㅡ;
소스코드가 짤림
헤더에서 저장했던 파일의 크기를 넘어서(예를들면 4k만큼해놨다면 4k+1에 해당하는부분에 메세지를 써넣는단 말인감?) 그리고 그게 원본파일에 영향을주지 않고
ㅇㅇ 그렇지. MsgBuild.exe 내용이 1234라면 애국가.exe를 생성할 때 1234동해물과.... 로 내용을 써서 저장하는 거지. 그리고 코드 상으로는 자기 자신을 open해서 뒤에 내용이 덧붙었나 확인하고 덧붙었으면 그거 처리하고 아니면 컴파일러로 동작.
엄밀하게 말하면 컴파일러라는 말은 틀리고 빌더지 그냥. 단순 메시지 출력이 아니라 파서를 짜면 간단한 프로그래밍 언어가 만들어진다.
이 방법을 쓰면 어셈이나 기계어를 전혀 몰라도 파서 짜는 것만 알면 간단하게 인터프리터 방식으로 돌아가는 exe 파일을 만드는 간단한 프로그래밍 언어를 짤 수 있어.
오호...... 오호
그부분을 전문적인 용어로 overlay 영역이라고 하고 실행파일에 추가 데이터나 사용자 리소스를 포함하는 용도로 사용 가능, 대표적으로 인스툴 파일이나 실행하면 압축이 풀리는 exe 형태의 zip 등 압축 파일이 overlay부분을 데이터로 사용함,
http://dblack.tk
커뮤니티 사이트 입니다 많은 이용 부탁 드립니다.