문제

나는 직장에서 무료 디지털 화성 컴파일러 (Naughty I Know)를 망쳐 놓고 컴파일링 된 기능을 검사하고 학습 목적으로 바이트 코드를 보는 코드를 만들어 컴파일러가 구축하는 방식에서 가치있는 것을 배울 수 있는지 확인했습니다. 그 기능. 그러나 MSVC ++에서 동일한 방법을 재현하는 것은 비참하게 실패했으며 내가 얻는 결과는 매우 혼란 스럽습니다. 다음과 같은 기능이 있습니다.

unsigned int __stdcall test()
{
  return 42;
}

그런 다음 나중에 나는한다 :

unsigned char* testCode = (unsigned char*)test;

이 경우 C ++ STATIC_CAST가 작동하도록 할 수없는 것 같습니다 (컴파일러 오류가 발생합니다). 따라서 C 스타일 캐스트이지만 요점 외에도 ... 참조 및 테스트를 사용해 보았습니다. 그러나 그것은 아무도 도움이되지 않습니다.

이제 TestCode에 의해 지적 된 메모리의 내용을 검사 할 때, 내가 보는 것은 유효한 코드처럼 보이지 않기 때문에 혼란스러워합니다. 심지어 디버그 브레이크 포인트가 거기에 갇혀 있습니다 ... 이와 같이 보입니다 (Target은 IA입니다. -32) :

0xe9, 0xbc, 0x18, 0x00, 0x00, 0xcc ...

이것은 분명히 잘못된 것입니다. 0xe9는 상대 점프 명령어이며 0xBC 바이트를 보면 다음과 같이 보입니다.

0xcc, 0xcc, 0xcc ...

IE 메모리는 할당되지 않은 메모리 또는 미사용 메모리에 대해 예상대로 디버그 브레이크 포인트 opcode에 초기화되었습니다.

42를 반환하는 기능에서 기대할 수있는 곳은 다음과 같습니다.

0x8b, 0x2a, 0x00, 0x00, 0x00, 0xc3

또는 최소한 MOV의 맛과 Ret (0xc2, 0xc3, 0xca 또는 0xcb)가 약간 더 아래로 향합니다.

MSVC ++가 보안상의 이유로 이런 종류의 일을하지 못하게하기위한 조치를 취하고 있습니까, 아니면 어리석은 일을하고 그것을 깨닫지 못하고 있습니까? 이 방법은 DMC를 컴파일러로 사용하여 잘 작동하는 것 같습니다 ...

나는 또한 다른 방법으로가는 데 어려움을 겪고 있지만 (바이트 실행), 근본 원인이 동일하다고 생각합니다.

모든 도움이나 팁은 대단히 감사하겠습니다.

도움이 되었습니까?

해결책

나는 단지 추측 할 수 있지만 디버그 빌드를 검사하고 있다고 확신합니다. 디버그 모드에서 MSVC ++ 컴파일러는 모든 통화를 통화로 점프 스텁을 대체합니다. 이것은 모든 기능이 실제 함수로의 점프로 시작한다는 것을 의미하며 이것이 바로 여기에 직면하고있는 것입니다.
주변 0XCC 바이트는 실제로 첨부 된 디버거를 발사하기 위해 실제로 중단 점 지침입니다.
릴리스 빌드로 동일하게 시도하십시오. 그것은 예상대로 작동해야합니다.

편집하다:이것은 실제로 링커 설정 /증분의 영향을받습니다. 릴리스 빌드에서 설명하는 효과가 표시되지 않는 이유는 이러한 점프 스텁이 모든 종류의 최적화가 켜져 있으면 간단하게 최적화되기 때문입니다 (물론 릴리스 빌드의 경우).

다른 팁

원하는 캐스트를 위해 :

unsigned char* testCode = reinterpret_cast<unsigned char*>( test );

프로젝트 -> properties-> c/c ++ -> general의 'EDIT & CONTUDE (/zi)'로 '프로그램 데이터베이스 (/zi)'로 '프로그램 데이터베이스 (/zi)'에서 디버그 정보 형식을 스위치하십시오. 컴파일러가 점프 코드를 삽입하여 디버거가 기능을 재구성하고 프로그램이 실행중인 동안 핫 패치를 제공 할 수있는 설정이라고 생각합니다. 아마도 '최소 재건 활성화'도 끄십시오.

MSVC에서 코드를 검사하는 훨씬 간단한 방법은 간단히 중단 점을 설정하고 분해를 검사하는 것입니다 (라인을 마우스 오른쪽 버튼으로 클릭하고 팝업 메뉴에서 'Goto 분해'를 선택하십시오. 소스 코드와 분해를 주석을 달게됩니다. 각 라인이 무엇을 컴파일하는지 볼 수 있습니다.

주어진 컴파일 된 기능에 대한 어셈블리 및 머신 코드를 보려면 /FACS 명령 줄 옵션을 컴파일러에 쉽게 제공하고 다음 .AMS 파일을 살펴볼 수 있습니다.

바이트 스트림에 함수 포인터를 캐스팅하기위한 정의 된 동작이 무엇인지 잘 모르겠습니다. 제대로 작동하지 않을 수도 있지만 추가 혼란의 원인 중 하나는 X86 기능이 모두 가변 크기이고 Little-Endian이라는 것입니다. .

이것이 증분 링크가 켜진다면, 당신이보고있는 것은 jmp [destination]. 디버거를 실행하고 분해가 무엇인지 확인할 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top