CIL nop opcode의 목적은 무엇입니까?


82

MSIL을 살펴보고 MSIL에 nop 지침 이 많이 있음을 알았습니다 .

MSDN 기사는 조치를 취하지 않으며 opcode가 패치되면 공간을 채우는 데 사용됩니다. 릴리스 빌드보다 디버그 빌드에서 더 많이 사용됩니다.

이러한 종류의 문이 어셈블리 언어에서 나중에 명령을 정렬하는 데 사용된다는 것을 알고 있지만 MSIL에서 MSIL nops가 필요한 이유는 무엇입니까?

(편집자 주 : 수락 된 답변은 질문이 원래 질문 한 MSIL / CIL NOP가 아니라 기계 코드 NOP에 관한 것입니다.)


19
언어 컴파일러에서 어셈블리로 내 보낸 MSIL nop 명령어와 어셈블리가 실행될 때 JIT 컴파일러에서 내 보낸 x86 nop 명령어 (해당 플랫폼에서) 사이에 이러한 답변에는 많은 혼란이 있습니다. [실제로 받아 들여지는 대답은 x86 nops에 관한 것이며 MSIL과는 관련이 없습니다.] 이상적으로이 질문은 MSIL의 목적 :: nop? 네이티브 플랫폼 nop의 목적?
Steve Steiner

답변:


107

NOP는 여러 가지 용도로 사용됩니다.

  • 이를 통해 생성 된 코드에서 다른 행과 결합 된 경우에도 디버거가 한 행에 중단 점을 배치 할 수 있습니다.
  • 로더가 다른 크기의 타겟 오프셋으로 점프를 패치 할 수 있습니다.
  • 이를 통해 코드 블록을 특정 경계에 정렬 할 수 있으므로 캐싱에 유용 할 수 있습니다.
  • 전체 함수 변경 크기에 대해 걱정할 필요없이 새 섹션에 대한 호출로 코드 청크를 덮어 쓰는 증분 링크를 허용합니다.

에서 위키 백과 : "A NOP는 가장 일반적으로, 위험을 방지하기 위해 같은 점프로 무효 기존의 명령을 렌더링하기 위해, 분기 지연 슬롯을 점유하거나 장소 홀더로 교체, 힘의 메모리 정렬에, 타이밍 목적으로 사용됩니다 나중에 프로그램 개발에서 활성 명령에 의해 (또는 리팩토링이 문제가되거나 시간이 많이 소요될 때 제거 된 명령을 대체) 경우에 따라 NOP는 사소한 부작용을 가질 수 있습니다. 예를 들어 Motorola 68000 시리즈 프로세서에서 NOP opcode는 파이프 라인의 동기화를 유발합니다. "
mbomb007

10

다음 은 디버깅에서 MSIL / CIL nops ( x86 기계 코드nop 아님)를 사용하는 방법입니다.

Nops는 암시 적 시퀀스 포인트를 정의하기 위해 언어 컴파일러 (C #, VB 등)에서 사용됩니다. 이것들은 기계 명령어가 IL 명령어로 다시 매핑 될 수 있도록 JIT 컴파일러에 알려줍니다.

DebuggingModes.IgnoreSymbolStoreSequencePoints 에 대한 Rick Byer의 블로그 항목 은 몇 가지 세부 정보를 설명합니다.

C #은 또한 호출 명령 뒤에 Nops를 배치하므로 소스의 반환 사이트 위치가 호출 이후의 라인이 아닌 호출이됩니다.


C #은 또한 호출 명령 뒤에 Nops를 배치하므로 소스의 반환 사이트 위치가 호출 이후의 라인이 아닌 호출이됩니다. 내가 이것을 얻는 지 확실하지 않습니다. 사용 가능한 참조가 있습니까?
user492238

8

릴리스 빌드가 아무 것도 방출하지 않는 코드에서 라인 기반 마커 (예 : 중단 점)에 대한 기회를 제공합니다.


중단 점이 nop에 있어야합니까? 일반 opcode에 중단 점을 두지 않는 이유는 무엇입니까?
Dan Goldstein

4
많은 일반 opcode가 릴리스 빌드에서 최적화됩니다. 중단 점이 여전히 가리키는 자리 표시자가 없으면 중단 점을 엉망으로 만들 것입니다.
Jimmy

1
디버그 빌드에서는 코드에 명령어가없는 곳에서 중단하는 명령어를 제공하는데도 사용됩니다. 예를 들어 여는 중괄호.
Greg D

1
blogs.msdn.com/oldnewthing/archive/2007/08/17/4422794.aspx 에 대한 참조를 소스로 추가 할 수 있습니다 .
Greg D

1
글쎄, 이것을 실제 대답으로 만들어 준 Greg와 Jimmy에게 감사드립니다.
harpo

6

또한 특정 프로세서 또는 아키텍처를 최적화 할 때 코드 실행 속도를 높일 수 있습니다.

오랫동안 프로세서는 대략 병렬로 작동하는 여러 파이프 라인을 사용하므로 두 개의 독립적 인 명령을 동시에 실행할 수 있습니다. 두 개의 파이프 라인이있는 단순 프로세서에서 첫 번째는 모든 명령어를 지원할 수있는 반면 두 번째는 하위 집합 만 지원합니다. 또한 아직 완료되지 않은 이전 명령의 결과를 기다려야 할 때 파이프 라인 사이에 약간의 지연이 있습니다.

이러한 상황에서 전용 nop 는 다음 명령어를 특정 파이프 라인 (첫 번째 파이프 라인 또는 첫 번째 파이프 라인 아님)으로 강제 적용하고 다음 명령어의 페어링을 개선하여 nop 의 비용 이 상각 된 금액 이상이 되도록합니다 .


5

친구! No-op은 굉장합니다! 시간 만 소비하는 명령입니다. 희미한 암흑 시대에는 중요한 루프에서 타이밍을 미세 조정하는 데 사용하거나 더 중요한 것은 자체 수정 코드의 필러로 사용합니다.


하드웨어에서 직접 실행되는 경우 사용을 이해하지만 MSIL은 JIT입니다.
Dan Goldstein

MSIL은 JIT가있는 시스템에서만 JIT됩니다. MSIL은 JIT를 요구하지 않습니다.
주각

5

최근에 작업 한 한 프로세서에서 (4 년 동안) NOP를 사용하여 다음 작업이 시작되기 전에 이전 작업이 완료되었는지 확인했습니다. 예를 들면 :

등록 할 값로드 (8주기 소요) nop 8 레지스터에 1 추가

이것은 레지스터가 추가 작업 전에 올바른 값을 가지고 있는지 확인했습니다.

또 다른 용도는 특정 크기 (32 바이트)가되어야하는 인터럽트 벡터와 같은 실행 단위를 채우는 것입니다. 필요합니다.


4

디버깅하는 동안 편집 및 계속 을 지원하는 데 사용할 수 있습니다 . 디버거에 오프셋 등을 변경하지 않고 이전 코드를 새 코드로 교체 할 수있는 공간을 제공합니다.


4
편집을 위해 VS에서 디버거 지원을 구현하고 계속합니다 (CLR 또는 컴파일러 부분을 구현하지 않았습니다). Nops는 메서드의 이전 버전에서 새 버전으로의 올바른 매핑을 보장하는 스토리의 일부입니다 (특히 예외 처리 코드에서 점프하는 경우). 그러나 MSIL 교체는 전체 기능별로 수행됩니다. CLR 관리 코드의 경우 해당 부분을 수행하기 위해 msil에 '공간을 남겨 둘'필요가 없습니다. 여기서 말하는 내용은 기본 편집과 관련하여 정확합니다.
Steve Steiner

4

다소 비 정통적인 사용은 버퍼 오버플로 익스플로잇에 사용되는 NOP-Slides 입니다.


이것을 찾고 있었다 :)
Suraj Jain

링크를 수정하십시오. 작동하지 않습니다. 404 찾을 수 없음을 제공하지 않으므로 항상 웹 아카이브 링크를 제출했는지 확인하십시오.
Suraj Jain

현재 쉘 코드 작업 중이며 NOP에 대한 더 많은 컨텍스트를 원했습니다. 조금 돌아 가야했다 그러나 여기 아카이브의 : web.archive.org/web/20110124015428/http://www.phreedom.org:80/...
saniboy

4

50 년이 늦었지만 헤이.

Nop는 어셈블리 코드를 직접 입력 할 때 유용합니다. 코드를 제거해야한다면 이전 opcode를 사용할 수 없습니다.

유사하게, 일부 opcode를 덮어 써서 새 코드를 삽입하고 다른 곳으로 이동할 수 있습니다. 거기에 덮어 쓴 opcode를 넣고 새 코드를 삽입합니다. 준비가되면 뒤로 뛰어 오릅니다.

때로는 사용 가능한 도구를 사용해야했습니다. 어떤 경우에는 이것은 매우 기본적인 머신 코드 편집기 일뿐입니다.

요즘 컴파일러를 사용하면 기술이 더 이상 의미가 없습니다.


3

이들의 고전적인 용도 중 하나는 디버거가 항상 소스 코드 행을 IL 명령어와 연결할 수 있도록하는 것입니다.


msil은 실행시 JIT 컴파일되므로 해당 매핑을 잃을 수 있습니다 (예 : 네이티브 명령어에는 고유 한 MSIL 명령어가 없음). NOP는 이러한 매핑을 유지하기 위해 언어 컴파일러에서 JIT 컴파일러로의 통신 메커니즘으로 사용됩니다.
Steve Steiner

3

소프트웨어 크래킹 장면에서 애플리케이션 잠금을 해제하는 고전적인 방법은 키 또는 등록 또는 기간을 확인하는 라인을 NOP로 패치하여 아무것도하지 않고 등록 된 것처럼 애플리케이션을 계속 시작하는 것입니다. .


5
나는 확신 무 조작 지시 :-) 도움 사람들의 해적 소프트웨어 발명되지 않은거야
사이먼 하워드

3

또한 자리 표시 자 (veeery old copy protection)로 수행되는 작업을 난독 화하도록 자체 수정하는 코드에서 NOP를 보았습니다.


3

ddaa가 말했듯이 nops를 사용하면 스택의 분산을 설명 할 수 있으므로 반환 주소를 덮어 쓸 때 nop 슬 레드 (연속 많은 nops)로 점프 한 다음 일부로 점프하는 대신 실행 가능한 코드를 올바르게 입력합니다. 시작이 아닌 명령어의 바이트.


1

이를 통해 링커는 긴 명령 (일반적으로 긴 점프)을 짧은 명령 (짧은 점프)으로 대체 할 수 있습니다. NOP는 추가 공간을 차지합니다. 다른 점프가 작동하지 않도록 코드를 이동할 수 없습니다. 이것은 링크 타임에 발생하므로 컴파일러는 길거나 짧은 점프가 적절한 지 알 수 없습니다.

적어도 그것은 그들의 전통적인 용도 중 하나입니다.


1

이것은 특정 질문에 대한 답변이 아니지만 예전에는 NOP를 사용하여 분기 지연 슬롯 을 채울 수있었습니다. 그렇지 않으면 유용한 지침으로 채울 수 없었습니다.


1

.NET 컴파일러가 MSIL 출력을 정렬합니까? IL에 대한 액세스 속도를 높이는 데 유용 할 수 있다고 생각합니다. 또한 이식 가능하도록 설계되었으며 다른 하드웨어 플랫폼에서는 정렬 된 액세스가 필요하다는 것을 이해합니다.


1

내가 배운 첫 번째 어셈블리는 SPARC이므로 분기 지연 슬롯에 익숙합니다. 다른 명령으로 채울 수없는 경우 일반적으로 분기 명령 위에 놓거나 루프에서 카운터를 증가시키려는 명령을 사용합니다. NOP.

크래킹에 익숙하지 않지만 NOP를 사용하여 스택을 덮어 쓰는 것이 일반적이라고 생각하므로 악성 기능이 시작되는 위치를 정확히 계산할 필요가 없습니다.


1

ISR에 들어간 후 누적 된 지연 시간을 자동으로 조정하기 위해 NOP를 사용했습니다. 타이밍을 잡는 데 매우 편리합니다.


-1

nop메모리 손상 악용 페이로드에 유용합니다. 물론 nop와 비슷한입니다xchg eax, eax


또 다른 답변 은 코드 삽입 익스플로잇에 대한 NOP 슬라이드를 이미 언급했습니다. 그래서 한 다른 답변 이 같은 질문에 대한합니다. 이 답변은 그것이 얼마나 유용한 지 언급하지 않으며 , 당신이 아직 모른다면 분명하지 않습니다.
Peter Cordes
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.