...
해당 함수는 다음과 같은 기능을 합니다.
player 변수의 값을 이용해 플레이어의 마크를 결정합니다.
saveMarkofBoard() 함수와 마크를 저장할 좌표 값(row, col)을 이용해gameinfo.Board[] 영역에 값을 저장합니다.
각종 함수를 이용해 플레이어가 마크를 저장하길 원하는 위치 값이 타당한지 확인합니다.
CheckBoardArea(), GetMarkForBoard(), checkLocation(), ...
입력한 위치 값이 정상적이지 않으면 메시지를 출력하고 프로그램을 종료합니다.
입력한 위치
값가값이 정상적이라면 해당 gameInfo를 gHistory[]에 저장합니다.
"operator new(0x80)" 코드에 의해 Heap 영역을 할당합니다.
할당된 Heap 영역의 주소 값을 gHistory[]변수에 저장합니다.
즉, 사용자가 입력한 좌표 값이 Heap 영역에 저장됩니다.
취약성은 여기서 발생합니다.
GameInfo 구조체를 사용하는 gHistory[]의 크기는 364 입니다.
gHistory[] 배열에 저장된 번호가 364를 넘는지에 대한 확인이 없습니다.
즉, 유저가 입력한 값이 364회가 넘으면 gPlayerGameInfo 영역에 Overflow됩니다.
Code Block | ||
---|---|---|
| ||
signed __int64 __fastcall SetMarkForBoard(GameInfo *gameinfo, unsigned int inputRow, unsigned int inputCol, int player, unsigned __int8 printOpt) { signed __int64 result; // rax signed int mark; // eax MAPDST bool v7; // al GameInfo *historyCount; // rax GameInfo *saveGameInfo; // ST30_8 signed int i; // [rsp+24h] [rbp-2Ch] unsigned int row; // [rsp+28h] [rbp-28h] unsigned int col; // [rsp+2Ch] [rbp-24h] if ( (unsigned __int8)GetMarkForBoard((__int64)gameinfo, inputRow, inputCol) == '.' ) { if ( player == 1 ) mark = 'O'; else mark = 'X'; saveMarkofBoard((__int64)gameinfo, inputRow, inputCol, mark); gameinfo->rowNumber = inputRow; gameinfo->colNumber = inputCol; for ( i = 0; i <= 3; ++i ) { row = dword_404FE0[i] + inputRow; col = dword_404FF0[i] + inputCol; v7 = (unsigned __int8)CheckBoardArea(row) ^ 1 || (unsigned __int8)CheckBoardArea(col) ^ 1; if ( !v7 && (char)GetMarkForBoard((__int64)gameinfo, row, col) == 0xA7 - mark && (unsigned int)checkLocation((__int64)gameinfo, row, col) == 0 ) { sub_4024C2((__int64)gameinfo, row, col); } } if ( (unsigned int)checkLocation((__int64)gameinfo, inputRow, inputCol) == 0 ) { if ( !printOpt ) print("Why you do this :(("); result = 0LL; } else if ( (unsigned __int8)sub_402528((__int64)gameinfo, printOpt) ) { if ( !printOpt ) print("Wanna Ko Fight?"); result = 0LL; } else { if ( printOpt != 1 ) { LODWORD(gameinfo->player) = mark; historyCount = (GameInfo *)operator new(0x80uLL); *historyCount = *gameinfo; saveGameInfo = historyCount; LODWORD(historyCount) = gHistoryCount++; gHistory[(signed int)historyCount] = saveGameInfo; } result = 1LL; } } else { if ( !printOpt ) print("You cheater!"); result = 0LL; } return result; } |
...