8086 머신 코드 (MS-DOS .COM), 83 바이트
DOSBox 또는 선호하는 증기 구동 컴퓨팅 엔진에서 실행할 수 있습니다. 조사 할 문자열은 명령 행 인수로 제공됩니다.
이진 :
00000000 : EB 28 28 8A 0E 80 00 49 BD 83 00 B4 02 51 8A 0E : .((....I.....Q..
00000010 : 80 00 BE 82 00 AC 39 EE 74 04 88 C2 CD 21 E2 F5 : ......9.t....!..
00000020 : 59 45 B2 0A CD 21 E2 E5 C3 90 EB D7 D7 8A 0E 80 : YE...!..........
00000030 : 00 49 BD 83 00 B4 02 51 8A 0E 80 00 BE 82 00 AC : .I.....Q........
00000040 : 39 EE 74 04 88 C2 CD 21 E2 F5 59 45 B2 0A CD 21 : 9.t....!..YE...!
00000050 : E2 E5 C3 : ...
읽을 수있는 :
cpu 8086
org 0x100
jmp part2
db 0x28
part1:
mov cl, [0x80]
dec cx
mov bp, 0x83
mov ah, 0x02
.l:
push cx
mov cl, [0x80]
mov si, 0x82
.k:
lodsb
cmp si, bp
je .skip
mov dl, al
int 0x21
.skip:
loop .k
pop cx
inc bp
mov dl, 10
int 0x21
loop .l
ret
nop
part2:
jmp part1
db 0xd7
mov cl, [0x80]
dec cx
mov bp, 0x83
mov ah, 0x02
.l:
push cx
mov cl, [0x80]
mov si, 0x82
.k:
lodsb
cmp si, bp
je .skip
mov dl, al
int 0x21
.skip:
loop .k
pop cx
inc bp
mov dl, 10
int 0x21
loop .l
ret
개요
활성 부분은 항상 복사에 의해 손길이 닿지 않도록 복제됩니다. 우리는 점프를 통해 건강한 버전을 선택합니다. 각 점프는 짧은 점프이며, 단지 2 바이트 길이이며, 두 번째 바이트는 변위입니다 (즉, 부호 결정 방향으로 점프 할 거리).
코드를 조사 할 수있는 네 부분으로 나눌 수 있습니다 : 점프 1, 코드 1, 점프 2 및 코드 2. 깨끗한 코드 파트가 항상 사용되도록하는 것이 좋습니다. 코드 부분 중 하나에 조사하면 다른 코드 부분을 선택해야하지만 점프 중 하나에 조사하면 두 코드 부분이 모두 깨끗해 지므로 어느 코드 부분을 선택해도 문제가되지 않습니다.
두 개의 점프 부품이있는 이유는 첫 번째 부품의 점프를 건너 뛰어 감지하는 것입니다. 첫 번째 코드 부분이 조사되면 마크에서 1 바이트 도착한다는 의미입니다. 우리가 그러한 벙치 착륙이 코드 2를 선택하고 적절한 착륙이 코드 1을 선택하면 우리는 황금색입니다.
두 점프 모두에 대해, 변위 바이트를 복제하여 각 점프 부분을 3 바이트 길이로 만듭니다. 이렇게하면 마지막 두 바이트 중 하나에 조사하면 여전히 점프가 유효 해집니다. 첫 번째 바이트의 조사는 점프가 발생하는 것을 막을 것입니다. 마지막 두 바이트는 완전히 다른 명령을 형성하기 때문입니다.
첫 점프를하세요 :
EB 28 28 jmp +0x28 / db 0x28
0x28
바이트 중 하나 가 제거되면 여전히 동일한 위치로 이동합니다. 경우 0xEB
바이트가 제거되고, 우리는 대신에 종료됩니다
28 28 sub [bx + si], ch
이것은 MS-DOS에 대한 양 성적 인 지침이며 (다른 맛은 동의하지 않을 수 있음) 코드 1로 넘어갑니다. 손상이 점프 1에 있었기 때문에 깨끗해야합니다.
점프를하면 두 번째 점프에 착륙합니다.
EB D7 D7 jmp -0x29 / db 0xd7
이 바이트 시퀀스가 손상되지 않고 마크에 바로 도달하면 코드 1이 깨끗하고이 명령이 해당 부분으로 이동한다는 것을 의미합니다. 변경된 변위 바이트가 손상된 변위 바이트 중 하나라도이를 보장합니다. 손상된 코드 1 또는 점프 1로 인해 1 바이트가 떨어지거나 0xEB
나머지 바이트가 손상된 경우 나머지 2 바이트도 양성입니다.
D7 D7 xlatb / xlatb
어떤 경우이든, 우리가이 두 명령을 실행하게되면 점프 1, 코드 1 또는 점프 2가 조사되어 코드 2로 넘어갑니다.
테스팅
다음 프로그램은 모든 버전의 .COM 파일을 자동으로 만드는 데 사용되었습니다. 또한 대상 환경에서 실행할 수있는 BAT 파일을 생성합니다.이 파일은 조사 된 각 바이너리를 실행하고 출력을 별도의 텍스트 파일로 파이프합니다. 출력 파일을 비교하여 검증하는 것은 쉽지만 DOSBox에는이 없기 fc
때문에 BAT 파일에 추가되지 않았습니다.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
FILE *fin, *fout, *fbat;
int fsize;
char *data;
if (!(fin = fopen(argv[1], "rb")))
{
fprintf(stderr, "Could not open input file \"%s\".\n", argv[1]);
exit(1);
}
if (!(fbat = fopen("tester.bat", "w")))
{
fprintf(stderr, "Could not create BAT test file.\n");
exit(2);
}
fseek(fin, 0L, SEEK_END);
fsize = ftell(fin);
fseek(fin, 0L, SEEK_SET);
if (!(data = malloc(fsize)))
{
fprintf(stderr, "Could not allocate memory.\n");
exit(3);
}
fread(data, 1, fsize, fin);
fprintf(fbat, "@echo off\n");
for (int i = 0; i < fsize; i++)
{
char fname[512];
sprintf(fname, "%03d.com", i);
fprintf(fbat, "%s Hello, world! > %03d.txt\n", fname, i);
fout = fopen(fname, "wb");
fwrite(data, 1, i, fout);
fwrite(data + i + 1, 1, fsize - i - 1, fout);
fclose(fout);
}
free(data);
fclose(fin);
fclose(fbat);
}