기본 콘텐츠로 건너뛰기

리버스엔지니어링바이블 01. 리버스 엔지니어링만을 위한 어셈블리

어셈블리는 한 번에 한가지 동작만을 한다.(더하기, 빼기, 옮기기). 특별히 여러 동작을 수행하는 opcode의 경우 자주사용되는 명령어 sequence를 묶어 하나로 만들어 놓은 것이다.

어셈블리는 익히는 것은 IA(Intel Arhchitecture)-32를 배우는 것을 의미한다.

레지스터는 CPU가 사용하는 변수이지만 사용 용도가 정해져있다. 하지만 바뀔 수도 있고 바꿀 수도 있다.
EAX : 산술 계산과 리턴값 저장
EDX : EAX와 비슷하지만 리턴값을 저장하지 않는다.
ECX : 루프문의 카운터
EBX : 여분의 레지스터
ESI,EDI : source에서 destination 으로 데이터를 옮기는 연산

바이트 저장 순서를 엔디언이라고 한다. 사람이 읽는 대로 저장하면 빅엔디언, 반대로 저장하면 리틀엔디언 이다. 인텔은 리틀엔디언을 사용한다.

연산은 레지스터 간에만 일어난다. 메모리끼리는 연산을 할 수가 없다.

코드 내에서 __declspec(naked)를 선언하면 컴파일러에 의한 코드를 삽입하지 않는다. 어셈블리 코딩을 할 경우 __asm을 선언한다.

함수 호출지 인자는 오른쪽에서 왼쪽으로 스택에 push된다. 인자가 push 되기 전에 리턴주소를 먼저 push하기 때문에 ebp+4 에는 리턴주소가 위치한다. 함수가 호출되어 지역변수공간을 할당할 때는 sub esp, 50h 와 같은 형태를 띈다. 지역변수는 스택에 할당한 순서대로 들어가기 때문에, 소스코드에서 가장위에 적은 변수가 가장 아래쪽에 쌓인다. 따라서 ebp에 가까울 수록 가장위의 지역변수다. ebp-4는 첫번째 지역변수이다. 가장 아래쪽에 쌓이긴 때문에 +를 통해 뒤쪽의 메모리주소를 가르켜야할꺼같지만, 스택은 메모리에서 메모리에서 반대로 자라기 때문에 -이다.

댓글

이 블로그의 인기 게시물

프로그래머스 - 행렬의 곱셈

머리속에서는 쉽지만 막상 구현하면 헷갈려서 잘 틀리는 행렬곱... class ProductMatrix { public int [][] productMatrix ( int [][] A , int [][] B ) { if ( A [ 0 ]. length != B . length ) return null ; int [][] answer = new int [ A . length ][ B [ 0 ]. length ]; for ( int i = 0 ; i < A . length ; i ++) { for ( int j = 0 ; j < B [ 0 ]. length ; j ++) { for ( int k = 0 ; k < B . length ; k ++) { answer [ i ][ j ]+=( A [ i ][ k ]* B [ k ][ j ]); } } } return answer ; } public static void main ( String [] args ) { ProductMatrix c = new ProductMatrix (); int [][] a = { { 1 , 2 }, { 2 , 3 } }; int [][] b = { { 3 , 4 }, { 5 , 6 } }; // 아래는 테스트로 출력해 보기 위한 코드입니다. System . out . println ( "행렬의 곱셈 : " + c . productMatrix ( a , b )); } }