안드로이드 기타/Frida

Frida 메모리(Memory) 모듈 정리

naroSEC 2023. 7. 12. 21:33

개요

Frida 스크립트 작성 시 C/C++ 로 작성된 네이티브 함수를 후킹할 때 인자 값 변조 및 확인을 위해 자주 사용되는 메모리(Memory) 모듈의 문법에 관해서 정리를 하고자 포스팅 한다. 해당 포스팅은 완결 판이 아니며, 추후 계속 추가될 예정이다.


Memory 모듈 사용법 및 설명

Memory 모듈이란?
앱의 메모리에 접근하고 조작하는 기능을 제공하며, 메모리 모듈을 사용하여 특정 주소의 메모리를 읽거나 쓰는 것이 가능하고 메모리 주소에 대한 포인터를 조작, 블록을 할당 및 해제 할 수 있도록 지원되는 모듈이다.

 

문법 및 사용법 예시

[ Memory.read ]

Memory.readInt(address)
address로 지정한 메모리 주소에서 4바이트 정수 데이터를 읽어 반환한다.
예: var value = Memory.readInt(buffer);

Memory.readInt8(address)
address로 지정한 메모리 주소에서 1바이트 부호 있는 정수 데이터를 읽어 반환한다.
예: var value = Memory.readInt8(buffer);

Memory.readUInt8(address)
address로 지정한 메모리 주소에서 1바이트 부호 없는 정수 데이터를 읽어 반환한다.
예: var value = Memory.readUInt8(buffer);

Memory.readInt16(address)
address로 지정한 메모리 주소에서 2바이트 부호 있는 정수 데이터를 읽어 반환한다.
예: var value = Memory.readInt16(buffer);

Memory.readUInt16(address)
address로 지정한 메모리 주소에서 2바이트 부호 없는 정수 데이터를 읽어 반환한다.
예: var value = Memory.readUInt16(buffer);

Memory.readInt32(address)
address로 지정한 메모리 주소에서 4바이트 부호 있는 정수 데이터를 읽어 반환한다.
예: var value = Memory.readInt32(buffer);

Memory.readUInt32(address)
address로 지정한 메모리 주소에서 4바이트 부호 없는 정수 데이터를 읽어 반환한다.
예: var value = Memory.readUInt32(buffer);

Memory.readInt64(address)
address로 지정한 메모리 주소에서 8바이트 부호 있는 정수 데이터를 읽어 반환한다.
예: var value = Memory.readInt64(buffer);

Memory.readUInt64(address)
address로 지정한 메모리 주소에서 8바이트 부호 없는 정수 데이터를 읽어 반환한다.
예: var value = Memory.readUInt64(buffer);

Memory.readByteArray(address, size)
address로 지정한 메모리 주소에서 size만큼의 데이터를 읽어 바이트 배열로 반환한다.
예: var result = Memory.readByteArray(buffer, 16);

Memory.readU8(address)
address로 지정한 메모리 주소에서 1바이트 부호 없는 정수 데이터를 읽어 반환한다.
예: var value = Memory.readU8(buffer);

Memory.readS8(address)
address로 지정한 메모리 주소에서 1바이트 부호 있는 정수 데이터를 읽어 반환한다.
예: var value = Memory.readS8(buffer);

Memory.readU16(address)
address로 지정한 메모리 주소에서 2바이트 부호 없는 정수 데이터를 읽어 반환한다.
예: var value = Memory.readU16(buffer);

Memory.readS16(address)
address로 지정한 메모리 주소에서 2바이트 부호 있는 정수 데이터를 읽어 반환한다.
예: var value = Memory.readS16(buffer);

Memory.readU32(address)
address로 지정한 메모리 주소에서 4바이트 부호 없는 정수 데이터를 읽어 반환한다.
예: var value = Memory.readU32(buffer);

Memory.readS32(address)
address로 지정한 메모리 주소에서 4바이트 부호 있는 정수 데이터를 읽어 반환한다.
예: var value = Memory.readS32(buffer);

Memory.readU64(address)
address로 지정한 메모리 주소에서 8바이트 부호 없는 정수 데이터를 읽어 반환한다.
예: var value = Memory.readU64(buffer);

Memory.readS64(address)
address로 지정한 메모리 주소에서 8바이트 부호 있는 정수 데이터를 읽어 반환한다.
예: var value = Memory.readS64(buffer);

Memory.readUtf8String(address)
address로 지정한 메모리 주소에서 UTF-8 형식의 문자열 데이터를 읽어 반환한다.
예: var str = Memory.readUtf8String(buffer);

Memory.readCString(address)
address로 지정한 메모리 주소에서 null 종료 C 문자열 데이터를 읽어 반환한다.
예: var str = Memory.readCString(buffer);

Memory.readByteArray(address, size)
address로 지정한 메모리 주소에서 size만큼의 데이터를 읽어 바이트 배열로 반환한다.
예: var result = Memory.readByteArray(buffer, 16);

 

[ Memory.write ]

Memory.writeByteArray(address, bytes)
bytes 배열의 데이터를 address로 지정한 메모리 주소에 쓴다.
예: var bytes = [0x41, 0x42, 0x43]; Memory.writeByteArray(buffer, bytes);

Memory.writeU8(address, value)
1바이트 부호 없는 정수 value를 address로 지정한 메모리 주소에 쓴다.
예: Memory.writeU8(buffer, 0x41);

Memory.writeS8(address, value)
1바이트 부호 있는 정수 value를 address로 지정한 메모리 주소에 쓴다.
예: Memory.writeS8(buffer, -1);

Memory.writeU16(address, value)
2바이트 부호 없는 정수 value를 address로 지정한 메모리 주소에 쓴다.
예: Memory.writeU16(buffer, 0x4142);

Memory.writeS16(address, value)
2바이트 부호 있는 정수 value를 address로 지정한 메모리 주소에 쓴다.
예: Memory.writeS16(buffer, -12345);

Memory.writeU32(address, value)
4바이트 부호 없는 정수 value를 address로 지정한 메모리 주소에 쓴다.
예: Memory.writeU32(buffer, 0x41424344);

Memory.writeS32(address, value)
4바이트 부호 있는 정수 value를 address로 지정한 메모리 주소에 쓴다.
예: Memory.writeS32(buffer, -12345678);

Memory.writeU64(address, value)
8바이트 부호 없는 정수 value를 address로 지정한 메모리 주소에 쓴다.
예: Memory.writeU64(buffer, 0x4142434445464748);

Memory.writeS64(address, value)
8바이트 부호 있는 정수 value를 address로 지정한 메모리 주소에 쓴다.
예: Memory.writeS64(buffer, -1234567890);

Memory.writeUtf8String(address, string)
string을 UTF-8 형식으로 인코딩하여 address로 지정한 메모리 주소에 쓴다.
예: Memory.writeUtf8String(buffer, "Hello");

Memory.writeCString(address, string)
string을 null 종료 C 문자열로 변환하여 address로 지정한 메모리 주소에 쓴다.
예: Memory.writeCString(buffer, "Hello");

 

[ 그 외 자주 사용하는 함수 ]

Memory.protect(address, size, protection)
address로 지정한 메모리 주소에서 size만큼의 메모리 보호 속성을 protection으로 설정합니다. protection은 --- (쓰기/읽기/실행 불가능), r-- (읽기만 가능), rw- (읽기/쓰기 가능) 등의 형식을 가진다.
예: Memory.protect(buffer, 64, 'rw-');

Memory.scan(address, size, pattern)
address로 지정한 메모리 주소에서 size만큼의 메모리 영역에서 pattern에 일치하는 값을 찾아 해당 주소의 배열로 반환한다.
예: var results = Memory.scan(buffer, 64, '01 23 45 ?? 67');

Memory.findPattern(base, size, pattern)
base로 지정한 메모리 주소부터 size만큼의 메모리 영역에서 pattern에 일치하는 첫 번째 주소를 찾아 반환한다.
예: var address = Memory.findPattern(Module.findBaseAddress('libfoo.so'), 0x10000, 'AB CD EF');

Memory.compare(address, pattern)
address로 지정한 메모리 주소와 pattern을 비교하여 값이 일치하는지 여부를 확인한다.
예: var isMatch = Memory.compare(buffer, [0x61, 0x62, 0x63]);

Memory.patchCode(address, size, callback)
address로 지정한 메모리 주소에서 size만큼의 코드를 임시적으로 변경하기 위해 callback 함수를 호출한다.
예: Memory.patchCode(buffer, 64, function (code) { ... });