2017-11-27 2 views
1

다른 함수를 통해 명령어가 호출 된 주소를 찾는 함수를 C 프로그램에 작성하는 방법이 있는지 궁금합니다.C 자체 어셈블리를 단계별로 실행하는 기능

예를 들어 ret 명령이 주 기능에서 사용되는 주소를 찾고 싶습니다.

첫 번째 생각은 "& main()"에서 시작하는 while 루프를 작성한 다음 현재 주소에서 명령이 "ret"되고 주소를 반환 할 때까지 매번 루프를 반복하여 주소를 1 씩 증가시키는 것입니다.

+2

는 그 일을 했습니까? .. –

+3

다른 86의 지침을 길이가 다르며 'ret'명령으로 오인 될 수있는 _immediate_ 데이터 값을 포함 할 수 있습니다. 또한 함수에는 둘 이상의 'ret'명령어가 있거나 'ret'명령어의 변형이있을 수 있습니다. –

+0

@OliverCharlesworth main()을 사용하여 증가 할 때 현재 주소에있는 명령어가 어떻게 해석 될지 모르겠습니다. – Ethan

답변

4

기계어 코드를 분해하는 프로그램을 작성할 수는 있습니다. (분명히 이것은 아키텍쳐에 따라 다르다.이 프로그램은 설계된 아키텍쳐에서만 작동한다.) 그런 프로그램은 main 루틴의 주소를 가지고 조사 할 수있다. (일부 C 구현에서는 함수 포인터가 실제로 함수 코드의 주소가 아니지만 코드를 역 어셈블하도록 설계된 프로그램은 이것을 계정으로 사용합니다.)

이것은 상당한 작업입니다 초보자를위한 어려움.

프로그램은 명령어 사이에 1 바이트 씩 주소를 증가시키지 않습니다. 많은 아키텍처는 4 바이트의 고정 명령 크기를 가지고 있지만 다른 크기도 가능합니다. x86-64 아키텍처 (다양한 이름으로 알려짐)에는 다양한 명령어 크기가 있습니다. 그것을 분해하는 것은 상당히 복잡합니다. 수업을 분해하는 과정의 일환으로 수업의 규모를 파악해야하므로 다음 강의의 위치를 ​​알 수 있습니다.

일반적으로 완료되면 main에 의해 실행되는 반환 명령을 결정하는 것이 항상 가능하지는 않습니다. 함수는 종종 간단한 방법으로 작성되지만 점프 할 수도 있습니다. 함수는 여러 개의 return 문을 가질 수 있습니다. 이 코드는 연속적이지 않은 여러 위치에있을 수 있으며 다른 기능과 코드를 공유 할 수도 있습니다. (이것이 일반적인 컴파일러에서 공통적 인 실행인지 여부는 알 수 없지만 실제로있을 수 있습니다.) 그리고 물론 main은 반환하지 않을 수도 있습니다. 컴파일러가이를 감지하면 반환 명령을 작성하지 않아도됩니다.

은 (덧붙여, 항상 프로그램이 종료 여부를 결정하는 프로그램을 작성하는 것은 불가능하다는 증명이있다.이 호출되는 Halting Problem.)

+0

이와 같은 심층 대응에 감사드립니다! 그 중 많은 부분이 아키텍처와 관련되어 있음을 이해합니다. 그러나 이러한 변수가 이상적인 상수라고 가정 할 수 있다면 (주 함수는 매우 간단하고 하나의 함수를 호출 한 다음 return 문이 0이고 그 것입니다.) 프로그램은 바이트를 반환 명령으로 인식 할 때까지 바이트를 읽을 수 있습니까? – Ethan

+0

아니요, 호출 명령어가 점프하는 주소 부분이 ret 명령어와 동일하지 않다는 보장은 없습니다. 이것은 매우 기본적인 것조차도 상당한 복잡성이있는 작업입니다. – SoronelHaetir

+0

가장 먼저 필요한 것은 명령의 경계를 찾을 수있는 것입니다. 즉, * 길이 *가 필요합니다. 다음은 x86-32 용 명령어의 길이를 계산하는 코드입니다. https://stackoverflow.com/a/23843450/120163이를 통해 opcode 바이트를 안정적으로 식별하고 지침을 디코딩 할 수 있습니다. 이를 사용하여 원하는대로 프로 시저 사냥의 지침을 단계별로 실행할 수 있습니다. –

관련 문제