진짜 간단한 첫 arm 리버싱이다.
#include<stdio.h> int test(int idx){ printf("In test%d\n",idx); } int main(int argc, char *argv[]){ int i; printf("In main\n"); for(i=0; i<5; i++){ test(i); } return 0; }
이런 간단한 코드로 일단 함수 인자 전달방식, for 문을 통한 분기문 등을 알아보자.
혹시 몰라서 바이너리를 올려놓는다.
첫 MOV R12, SP 는 R12 에 SP 를 저장하는것 같다.
STMFD 는 블럭 전송이라고 하는데 push 랑 같다고 보면 될거같다...?
R11 = R12 - 4 를 해주고, SP 에서 0xC 만큼 감소 시켜준다.
아마 위에서 4줄까지가 함수의 프롤로그 부분인듯 싶다.
그후 STR 명령어로 R11 - 0x10, R11 - 0x14 부분에 각각 R0, R1값을 저장해준다.
R11 이 아마 main 시작시 SP - 4 값을 가지고 있을 테고, 여기에 -0x10, -0x14 한 부분에 R0, R1 을 일단 저장해 놓는다. 아마 canary 같은 보호기법이 아닐까 생각해본다.
그 후 R0 에 "In main\n" 의 주소값을 저장해주고 printf 를 호출한다.
그리고 R3 에 0 을 저장하고, R11 - 0x18 부분에 R3( 0 ) 을 저장하게 된다. R11 - 0x18 부분에는 아마 우리가 반복을 돌기 위해 선언한 i 의 위치인것 같다.
loc_8218 부분이 반복을 돌리는 부분이다.
R3 에 R11 - 0x18, 즉 변수 i 값을 저장하고 4 랑 비교를 한다. 비교를 했을때 ZF 가 Clear 된 상태이며 NF == VF 이면 loc_823C , main 종료부분으로 뛰게된다
그게 아니라면 R0 에 i 값을 저장하고 test 를 호출한다.
호출하게된 test 에서는 아까 보았던 함수 프롤로그를 하고,
R11 - 0x10 부분에 인자로 받은 i 값을 저장한다.
그리고 R0 에는 "In test%d\n"의 주소값을, R1 에는 아까 저장한 i 값을 가지고, printf 를 호출한다.
마지막 2줄은 함수의 에필로그로 보이는데, R3 의 값을 R0 에 저장하고 ( 함수의 리턴값 ), LDMFD 아까 STMFD 와 반대, 즉 pop 을 하는 명령어를 실행 시키고 끝낸다.
반복문으로 돌아와서, R3 에 R11-0x18 안의 즉 i 값을 저장하고, ADD 로 1 을 더해준 후, 다시 R11 - 0x18 에 저장한 다음, loc_8218 로 뛴다.
이런식으로 반복을 하고 CMP R3, #4 를 만족해서 BGT 를 실행시켜 점프를 하게되면,
R3 에 0 을 넣고, R0 에 R3, 즉 main 의 리턴값을 0 으로 해주고, 함수의 에필로그를 해주고 끝낸다.
이런식으로 간단한 프로그램을 한줄한줄 분석해 보았다.
많이 간단했지만, 역시 처음은 이렇게 간단한 것이라도 한줄한줄 분석하면서 눈에 익히는게 맞다고 본다.
'Reversing' 카테고리의 다른 글
[CodeGate] RamG (0) | 2018.01.05 |
---|---|
[???] cuty (2) | 2017.12.05 |
[Reversing.kr] Replace (4) | 2017.11.13 |
[DIMICTF2017] ToHard (0) | 2017.07.17 |