BOB

[BOB] NES Emulator Architecture

Posted by MrBIN on February 15, 2017

※ BOB를 마무리하고 진행했던 NES 에뮬레이터 분석에 관한 내용을 망각하지 않기 위해 쓰는 글
취약점에 대한 내용은 보안상 작성하지 않음

NES Emulator

img0

  • NES Emulator는 닌텐도 엔터테인먼트 시스템의 하드웨어와 소프트웨어 동작을 소프트웨어적으로 모방하여, 원래 콘솔 없이도 PC, 스마트폰 등의 기기에서 NES 게임을 실행할 수 있게 해주는 프로그램.
  • 에뮬레이터는 윈도우에서 구동할 수 있도록 가상화해서 사용하며 최신 버전은 0.97 버전.
  • Doc : https://www.emulator-zone.com/doc.php/nes/

img1

NES Emulator Architecture

  • Doc : https://www.nesdev.org/NESDoc.pdf
  • Source : https://github.com/yamanyandakure/VirtuaNES097
CPU (Central Processing Unit)
* CPU(Central Processing Unit)는 6502기반의 소리를 핸들링하는 기술인 pAPU를 추가한 2A03을 사용
* 16 bit 주소를 사용하므로 총 64KB이며 절반인 32KB는 Cartridge ROM의 공간
* 32KB로 게임을 실행하기엔 너무 작기 때문에 MAPPER를 사용해 뱅크 스위칭 해줌

img2

-CPU Registers- img3 -Instructions- img4

PPU (Picture Processing Unit)
* 그래픽 출력을 담당하는 커스텀 칩으로 카트리지 내의 CHR-ROM에서 실제 그래픽 데이터 가져옴
* 레지스터는 CPU의 $2000 ~ $2007를 통해 CPU의 제어를 받는다. 추가로 DMA 사용을 위해 $4014 레지스터를 사용
* Color Palettes, Pattern Tables, Name Tables, Attribute Tables를 통해 출력할 이미지를 결정하고 Scrolling 기능으로 화면에 출력
* Pattern Table : 화면의 패턴을 저장한 테이블
* Name Table : Pattern Table에 인덱싱하여 출력할 화면으로 재배열한 테이블
* Attribute Table : 화면의 색상 정보를 저장한 테이블

img5

MMC (Multi Memory Controller) > MAPPER
* 닌텐도 패밀리 컴퓨터의 게임 카트리지에 사용된 메모리 관리칩
* CPU에서 원하는 데이터가 있는 곳으로 메모리 영역을 지속적으로 변경해줌
* 매퍼는 게임 개발자가 게임에 맞는 매퍼를 사용하거나 개발
* 일부 MMC는 메모리 관리 기능 뿐 아니라 추가 사운드나 그래픽 기능도 있음
* MAPPER는 메모리 제어와 깊은 연관이 있기 때문에 취약점이 발생할 가능성이 높은 대상
PRG-ROM
* 게임의 코드 데이터를 관리하는 데이터 메모리
CHR-ROM
* 게임의 그래픽 데이터를 관리하는 데이터 메모리
WRAM
* 게임 SAVE를 위한 램
ROM 구조
* 매직넘버(4 byte), PRG BANK 개수(1 byte), CHR BANK 개수(1 byte), 플래그(10 byte)
* PRG BANK: 16KB씩 최대 16개 PRG-ROM에 해당
* CHR BANK: 8KB씩 최대 8개 CHR-ROM에 해당

img6

NES Flow

!img7

Cutom Rom File
  • 에뮬레이터 동적 분석을 위해선 커스텀한 롬 파일 제작이 필요
  • 아래 코드를 통해 간단한 롬 파일 제작 가능
/*
   Hello, NES!
   writes "Hello, NES!" to the screen
   written by WolfCoder (2010)
*/

/* Includes */
#include <nes.h>

/* Writes the string to the screen */
/* Note how the NES hardware itself automatically moves the position we write to the screen */
void write_string(char *str)
{
   /* Position the cursor */
   /* We only need to do this once */
   /* This is actually 2 cells down since the first 8 pixels from the top of the screen is hidden */

   *((unsigned char*)0x2006) = 0x20;
   *((unsigned char*)0x2006) = 0x41;

   /* Write the string */
   while(*str)
   {
      /* Write a letter */
      /* The compiler put a set of graphics that match ASCII */
      *((unsigned char*)0x2007) = *str;
      /* Advance pointer that reads from the string */
      str++;
   }
}

/* Program entry */
int main()
{
   /* We have to wait for VBLANK or we can't even use the PPU */
   waitvblank(); /* This is found in nes.h */

   /* This is a really strange way to set colors, don't you think? */
   /* First, we need to set the background color */
   *((unsigned char*)0x2006) = 0x3F;
   *((unsigned char*)0x2006) = 0x00;
   *((unsigned char*)0x2007) = 1;

   /* Then, we need to set the text color */
   *((unsigned char*)0x2006) = 0x3F;
   *((unsigned char*)0x2006) = 0x03;
   *((unsigned char*)0x2007) = 0x30;

   /* We must write our message to the screen */
   write_string("Hello, NES!");

   /* Set the screen position */
   /* First value written sets the X offset and the second is the Y offset */
   *((unsigned char*)0x2005) = 0x00;
   *((unsigned char*)0x2005) = 0x00;

   /* Enable the screen */
   /* By default, the screen and sprites were off */
   *((unsigned char*)0x2001) = 8;

   /* Wait */
   /* The compiler seems to loop the main function over and over, so we need to hold it here */
   while(1);
   return 0;
}
  • 컴파일하고 얻은 rom 파일을 에뮬레이터에 올리면 잘 나옴. !img8



Ref.

https://www.emulator-zone.com/doc.php/nes/
https://www.nesdev.org/NESDoc.pdf
https://github.com/yamanyandakure/VirtuaNES097
https://en.wikipedia.org/wiki/Bank_switching
http://www.bigmessowires.com/2010/06/19/bank-switching/
https://github.com/PyAndy/Py3NES
https://github.com/billymeter/pyNES
https://github.com/emullinix/NES/blob/master/EvanNES/CPU.py
https://wiki.nesdev.com/w/index.php/INES
http://datacrystal.romhacking.net/wiki/Super_Mario_Bros_3:RAM_map
http://www.romhacking.net/documents/
http://search.cpan.org/dist/Games-NES-ROM/lib/Games/NES/ROM.pm
http://fms.komkon.org/EMUL8/NES.html
http://nesdev.icequake.net/
http://www.joinc.co.kr/w/Site/Assembly/Documents/ProgrammingGroundUp/index.html