외로운 Nova의 작업실

안드로이드 리버싱 - 3(Smali 문법 정리) 본문

Mobile App Penetesting/Android Reversing

안드로이드 리버싱 - 3(Smali 문법 정리)

Nova_ 2023. 3. 22. 17:27

- Smali

안드로이드는 달빅 가상머신위에서 돌아갑니다. 달빅 가상머신의 Smali는 어셈블리어와 비슷합니다. 따라서 리버싱을할때 어셈블리어를 알아야되듯이 안드로이드 리버싱을 할때는 Smali를 알아야합니다.

 

- Smali 문법

실제 문법의 경우에는 안드로이드 개발자 사이트에 자세히 나와있습니다.

https://source.android.com/docs/core/runtime/dalvik-bytecode?hl=ko 

 

Dalvik 바이트 코드  |  Android 오픈소스 프로젝트  |  Android Open Source Project

Dalvik 바이트 코드 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. 일반 디자인 머신 모델과 호출 규칙은 일반적인 실제 아키텍처와 C 스타일 호출 규칙을 거

source.android.com

 

- Smali 문법 정리

따로 다른분께서 자세히 정리하신 부분도 적어놓겠습니다.

- nop
  아무 것도 하지 않는 것입니다.

- move vA, vB
  A: 목표 레지스터(4bits), B: 소스 레지스터(4bits)
  A값에 B값을 넣어 주는 것입니다. (C언어로 A = B)

- move-result vAA
  A: 목표 레지스터(8bits)
  직전의 invoke-... 함수 호출의 결과를 A에 넣어 줍니다.

- return-void
  아무 것도 없이 리턴합니다.

- return vAA
  A: 목표 레지스터(8bits)
  4byte까지의 데이터를 리턴합니다.
  
- return-object vAA
  A: 목표 레지스터(8bits)
  단순 변수가 아닌 Object를 리턴할 때 사용합니다.

- const/4 vA, #+B
  A: 목표 레지스터(4bits), B: 정수(4bits)
  B(4바이트까지 부호확장?)에 지정된 값을 A에 넣어 줍니다.
 
- const/16 vAA, #+BBBB
  A: 목표 레지스터(8bits), B: 정수(16bits)
  B(4바이트까지 부호확장?)에 지정된 값을 A에 넣어 줍니다.
  
- const vAA, #+BBBBBBBB
  A: 목표 레지스터(8bits), B: 임의의 4바이트 상수
  B에 지정된 상수 값을 A에 넣어 줍니다.

- const-string vAA, string@BBBB
  A: 목표 레지스터(8bits), B: 문자열
  B에 지정된 문자열에 대한 참조를 A에 넣어 줍니다.

- array-length vA, vB

  A: 목표 레지스터(4bits), B: 배열 참조 레지스터(4bits)
  B로 지정된 배열의 길이로 A에 저장합니다.
 
- new-array vA, vB, type@CCCC
  A: 목표 레지스터(8bits), B: 사이즈 레지스터, C: 타입
  C로 지정한 형식으로 B로 지정한 사이즈로 배열 A를 만듭니다.

- goto +AA
  A: 분기할 오프셋(8bits)
  무조건 A로 지정된 오프셋으로 분기합니다.

- if-.... vA, vB, +CCCC
  A: 비교할 첫번째 레지스터(4bits), B: 비교할 두번째 레지스터(4bits)
  C: 분기할 오프셋(16bits)
  지정한 A, B 두 레지스터 값을 비교하여 C로 지정된 오프셋으로 분기합니다.
  if-eq: A = B, if-ne: A != B(다르다), if-lt: A < B
  if-ge: A >= B, if-gt: A > B, if-le: A <= B
 

- if-....z vAA, +BBBB
  A: 비교할 레지스터(8bits), B: 분기할 오프셋(16bits), 주로 :cond_0
  지정한 A 레지스터 값을 0과 비교하여 B로 지정된 오프셋으로 분기합니다.
  if-eqz: A = 0, if-nez: A != 0(다르다), if-ltz: A < 0
  if-gez: A >= 0, if-gtz: A > 0, if-lez: A <= 0
  

- invoke-.... {vC, vD, ...}, meth@BBBB
  B: 참조할 함수, C,D,... 함수의 인수
  B로 지정한 함수를 실행합니다.
  결과는 위에서 설명한 move-result 로 받을 수 있습니다.
  invoke-virtual, invoke-direct, invoke-static, ... 등이 있습니다.

- unop vA, vB
  A: 목표 레지스터(4bits), B: 소스 레지스터(4bits)
  소스 레지스터B로 단항연산을 수행 후 목표 레지스터A에 결과를 저장합니다.
  neg-int, neg-long, neg-float, neg-double: A = -B
  not-int, not-long: A = ~B
  int-to-long: int64 A = (int64) B; int32 B;
  int-to-float: float A = (float) B; int32 B;
  int-to-double: double A = (double) B; int32 B;
  ...
 
- binop vAA, vBB, vCC
  A: 목표 레지스터(8bits),
  B: 첫번째 소스 레지스터(8bits), C: 번째 소스 레지스터(8bits)
  두 소스 레지스터 B, C로 부터 지정된 바이너리 연산을 수행 후 목표 레지스터A에 결과를 저장합니다.
  add-int, add-long, add-float, add-double: A = B + C
  sub-int, sub-long, sub-float, sub-double: A = B - C
  mul-int, mul-long, mul-float, mul-double: A = B * C
  div-int, div-long, div-float, div-double: A = B / C
  rem-int, rem-long, rem-float, rem-double: A = B % C (B/C의 나머지)
  and-int, and-long: A = B & C (And)
  or-int, or-long: A = B | C(Or)
  xor-int, xor-long: A = B ^ C(Exclusive Or)
  shl-int, shl-long: A = B << (C&0x1f) (Shift Left)
  shr-int, shr-long: A = B >> (C&0x1f) (Shift Right)
  ushr-int, ushr-long: A = B >> (C&0x1f) (Shift Right)(Unsigned)
  

- binop/2addr vA, vB
  A: 목표+첫번째 소스 레지스터(4bits), B: 두번째 소스 레지스터(4bits)
  소스 레지스터 A, B로 부터 지정된 바이너리 연산을 수행 후 첫번째 소스 레지스터A에 결과를 저장합니다.
  add-int/2addr, add-long/2addr, add-float/2addr, add-double/2addr: A = A + B
  sub-int/2addr, sub-long/2addr, sub-float/2addr, sub-double/2addr: A = A - B
  mul-int/2addr, mul-long/2addr, mul-float/2addr, mul-double/2addr: A = A * B
  div-int/2addr, div-long/2addr, div-float/2addr, div-double/2addr: A = A / B
  rem-int/2addr, rem-long/2addr, rem-float/2addr, rem-double/2addr: A = A % B
  and-int/2addr, and-long/2addr: A = A & B
  or-int/2addr, or-long/2addr: A = A | B
  xor-int/2addr, xor-long/2addr: A = A ^ B
  shl-int/2addr, shl-long/2addr: A = A << (B&0x1f)
  shr-int/2addr, shr-long/2addr: A = A >> (B&0x1f)
  ushr-int/2addr, ushr-long/2addr: A = A >> (B&0x1f)(Unsigned)

- binop/lit16 vA, vB, #+CCCC
  A: 목표 레지스터(4bits),
  B: 소스 레지스터(4bits), C: 정수 상수(16bits)
  소스 레지스터 B와 상수C로 부터 지정된 바이너리 연산을 수행 후 목표 레지스터A에 결과를 저장합니다.
  add-int/lit16: A = B + C
  rsub-int: A = C - B (역 뺄샘)
  mul-int/lit16: A = B * C
  div-int/lit16: A = B / C
  rem-int/lit16: A = B % C
  and-int/lit16: A = B & C
  or-int/lit16: A = B | C
  xor-int/lit16: A = B ^ C
 
- binop/lit8 vAA, vBB, #+CC
  A: 목표 레지스터(8bits),
  B: 소스 레지스터(8bits), C: 정수 상수(8bits)
  소스 레지스터 B와 상수C로 부터 지정된 바이너리 연산을 수행 후 목표 레지스터A에 결과를 저장합니다.
  add-int/lit8: A = B + C
  rsub-int/lit8: A = C - B (역 뺄샘)
  mul-int/lit8: A = B * C
  div-int/lit8: A = B / C
  rem-int/lit8: A = B % C
  and-int/lit8: A = B & C
  or-int/lit8: A = B | C
  xor-int/lit8: A = B ^ C

 

- Smali 샘플

Smali를 이해하기 위한 좋은 샘플은 아래 링크에 있습니다.

http://androidcracking.blogspot.com/2011/01/example-structuressmali.html

 

example-structures.smali

many people find this blog by searching for smali syntax examples and finding a previous post on example smali syntax . since i originally ...

androidcracking.blogspot.com

 

Comments