Ghidra(기드라 : 역어셈블리 툴) 를 Duckstation (플레이스테이션1 에뮬) 에 연결하여 PS1 코드 분석 시작 방법 기록


 시간이 소모되어 기록.


 Ghidra 는 미국 국가 안보국(NSA)에서 만들어 오픈 소스로 공개한 역어셈블리어 프레임워크 라고 한다.

 (출처: https://ndb796.tistory.com/323 [안경잡이개발자:티스토리])


 아래 항목중 막히는 부분이 있다면 챗GPT(본인은 유료 사용)에게 물어보면 알려줄 것이다. 

 무료로 쓸 경우 구글 제미나이는 코드분석에는 괜찮으나, 이런 안내에는 꽝이다.


 필요한 툴들 및 준비 (좀 많음)

 쓰려면 JDK(자바 개발킷) 가 설치되어 있어야 한다. 옛날엔 JRE 라는, 개발없이 쓰기만 하는 사람용 파일이 있었으나 JDK로 통합되어서 어쩔수 없이 JDK를 설치해야 한다.


 * 주의사항 : Ghidra와 GDB 압축푸는 폴더는 루트폴더면 안된다. 하위폴더 하나 만들어 거기에 압축을 푼다.


* Ghidra 다운로드 깃허브 : https://github.com/nationalsecurityagency/ghidra

 (압축만 풀면 되는 편한 방식임)

* 오라클 JDK 다운로드 페이지 https://www.oracle.com/java/technologies/downloads/#java11-windows


 아래 과정은 전부 Ghidra 와 Duckstation 을 연결할때 오류를 수정하기 위해 하는 것이다.

 안한다면 항목마다 오류를 보게 될것이다.


■ Noward GDB 압축 풀기 + 파이썬 및 pip 설치

 Ghidra와 Duckstation(덕스테이션) 과의 연결을 하기 위해서는 GDB 라는 게 필요한데, 그냥 GDB는 안되고, 다음 조건을 만족해야 한다.

- PS1의 MIPS 3000 어셈블리 해석이 될 것 + 파이썬 지원 + xml 지원

 => noword GDB 라는게 있었다


* noward GDB 깃허브 : https://github.com/noword/GDB-Windows-Binaries 의 Code 버튼 -> Download ZIP 을 눌러 다운받고 압축해제.

 실행파일을 보면 파이썬3.10 까지만 지원되는걸 알 수 있다.

 정확히 파이썬 3.10 을 설치해야 한다. (높은 버전도 될것 같긴 한데 안해봄. 해보면 수정)


* 파이썬 3.10 다운로드 : https://www.python.org/downloads/release/python-3100/ 

 (시간지나면 정책에 의해 링크 잘릴수도 있음. 그러면 어쩔수없이 나중버전 설치해야 할듯)


=> 파이썬 설치시 폴더는 본인이 custom으로 지정 추천, 설치폴더의 python310.lib 을 noward GDB 압축푼 폴더(실행파일이 있는 폴더) 에 넣는다.

 인스톨러 첫 화면에서 '자동으로 PATH 등록' 비슷한 옵션에 체크한다. 만일 빼먹었다면, 고급시스템설정 환경변수 -> 사용자변수 PATH 에 파이썬이 설치된 폴더와 하위폴더인 \Scripts\ 를 추가해야 한다.


* pip (패키지 인스톨러) 설치 

 파이썬 설치시 \scripts\ 폴더에 pip 이 없으면 설치해야 하는데, cmd 에서 다음을 입력

python.exe -m ensurepip --upgrade

 그럼 pip 파일이 생길 것이다.


■ CMD에서 'Powershell' 실행하여 권한변경

 Powershell 에서 다음을 실행하여 Y를 누른다.

Set-ExecutionPolicy -Scope CurrentUser RemoteSigned

Powershell Setting


■ Ghidra 에 포함된, 필요한 파이썬 패키지 설치

* cmd에서 다음 두개를 입력해 설치 (경로에서 <기드라 압축푼경로>는 직접 수정)

▶ 1.

py -3.10 -m pip install --no-index ^

  --find-links "<기드라 압축푼경로>\Ghidra\Debug\Debugger-rmi-trace\pypkg\dist" ^

  "<기드라 압축푼경로>\Ghidra\Debug\Debugger-rmi-trace\pypkg\dist\ghidratrace-12.1-py3-none-any.whl"


▶ 2.

py -3.10 -m pip install --no-index ^

  --find-links "<기드라 압축푼경로>\Ghidra\Debug\Debugger-rmi-trace\pypkg\dist" ^

  --find-links "<기드라 압축푼경로>\Ghidra\Debug\Debugger-agent-gdb\pypkg\dist" ^

  "<기드라 압축푼경로>\Ghidra\Debug\Debugger-agent-gdb\pypkg\dist\ghidragdb-12.1-py3-none-any.whl"


■ Ghidra 내부 코드수정 (알려지지 않은 레지스터이름을 받았을때 pass 처리)

 (챗GPT의 안내로 수정된 파일임)

▶ <기드라 압축푼경로>\Ghidra\Debug\Debugger-agent-gdb\pypkg\src\ghidragdb\commands.py

  파일을 열어서 615줄 쯤에 있는 putreg 함수를 수정해야 하는데, 복붙하자면 길어지니 수정된 commands.py 파일 링크

: https://drive.google.com/file/d/1VzomzBB5PORi75ZQCX7-PGllkg_ItfY3/view?usp=drive_link

 (원본 파일을 백업해 두고 싶으면 마음대로)


Duckstation 포트 열기 등

* (0.1.11752 버전이었음) 고급설정에 '디버그 메뉴 표시' -> '디버깅' 탭에서 'GDB서버 활성화 체크'  이러면 Ghidra에서 localhost 를 써서 연결할 수 있게 된다.

Duckstation_Setting_Debug on

- 게임 실행 후 일시정지 해놓아도 디버거는 작동한다.


* 디버거 열기 : 위쪽메뉴 '디버그' -> CPU 디버거

* 메모리는 '도구' -> '메모리 편집기' 이다.

* 치트(값 찾기) 는 '도구' -> '메모리 스캐너' 이다.

mem scanner
▲ 헷갈리게 되어있는데, 값 찾을때 같은 값을 찾으려면 반드시 '값과 같음'을 골라야 한다.



Ghidra 에서 프로젝트 생성 및 연결

* 프로젝트 생성후 File -> import File 을 한다.

 (Import 한 파일은 프로젝트 내부에 복사되므로 다음에 열 때 해당파일 없어도 OK.)

 PS1 게임 CD 내용을 보면 '비밀결사Q' 의 경우에는 PSX.EXE 가 있고, SLPS_013.34 파일이 있다. (헥스에디터로 열어보면 헤더 문자가 보이긴 함) PSX.EXE 실행 -> SLPS_013.34 순으로 로드되는 것 같다.


 SLPS_013 파일을 import 한다. 헤더 정보에 따라 다음과 같이 입력(ai가 해석해 주니 HxD로 직접 보는것보다 편할것이다)

- Language 선택 : MIPS / default / 32 little / default

select language

Ghidra_Import_ps1


 더블클릭하면 Code Browser 가 열리지만, 디버거를 열어야 한다.

* 프로젝트 파일 우클릭 -> Open With -> Debugger 선택하여 디버거 열기


* 디버거에서 중간 위쯤 벌레모양을 눌러 gdb remote 를 누른다.

OPEN GDB REMOTE

gdb remote setting
- Port는 덕스테이션 메뉴에서 나오는 포트번호 (변경가능)
- gdb 경로는 본인의 gdb 경로를 지정한다. 본인은 gdb-py310.exe 를 지정했다.


=> Launch 버튼을 누르면 연결 시도이다. 다른 에러메세지 없이 아래 메세지가 뜨면 연결은 된 것일 거다.

 ▲ 원래 에러나는걸, commands.py 를 수정해서 패스하게 만들어 뜨는 메세지들임.


■ Static Listing 과 Dynamic Listing 동기화

* 두 화면이 동기화 되어야 한다

 근데 과정을 마쳐도 Static Listing 은 자동으로는 바뀌지 않고, 위의 Dynamic Listing 을 클릭해야 바뀌는 듯

static,dynamic listing

* 메뉴 Window -> Debugger -> Static Mapping
Static Mapping

* 위아래 램 범위 입력 : 80010000 ~ 800b2fff (아래는 자동으로 a3000 이 됨)
 ★ 프로젝트 저장시 저장이 안되는것 같다. 열때마다 SLPS~ 파일 열고 이 창에서 입력해야 하는듯.
ram range

■ 레지스터 창 열기

* Window -> Debugger -> Registers 이다.

registers


■ 만약 프로젝트 다시 열었을때 Static Listing 창이 안보인다면

 * 메뉴에서 다시 open 한다 : File -> Open -> ex) SLPS_013.34

Open to view static listing
+ 위에 「Static Listing 과 Dynamic Listing 동기화」 다시 수행

■ 메모리 뷰어는 New Memory View이다.

 근데 Static Listing 에서 PC주소와 동기화 돼버리는데, 안되게 하는게 어렵다.

* Window -> Debugger -> New memory view
 ★ 왼쪽 Byte Viewer 메뉴에 Memoryview, ByteView 같은게 있지만 이건, PC가 이동함에 따라 메모리 주소도 같이 이동되어 버린다.
 동기화 되지않고 고정되어 있는 메모리뷰는 스샷처럼 New Memory View 로 열어야 한다.

 * 주소이동 단축키 : G (다른 프로그램들에선 보통 Ctrl+ G 임)

 * 화살표아이콘? -> Do not track 골라야 동기화 안되는듯 (PC가 진행돼도 안따라가고 가만히 있음)


■ 디버깅 시작

 이제 F10을 눌러보면 진행이 될텐데 Duckstation 의 디버거에서도 진행이 되면 정상이다.

 Ghidra 에서는 코멘트 달기 등이 가능하다. 코멘트 종류가 여러가지인데 EOL 이 줄 오른쪽에 다는 것.

set end

주로 Static Listing 에서 진행하게 될 듯


 나머진 더 써보고 기록할거 있으면 기록.


* MIPS3000 특징

- lw 같은 로드 명령이나 점프명령은 딜레이가 있어 명령어 1개 지난 후에 결과가 반영된다.





댓글 없음:

댓글 쓰기