x86マシンコード(32ビット)、256バイト
コードページ437コンソールでコードを印刷すると、次のように表示されます。
j XI a I a I a jbZ Q fiQ Gf a f Q I a I a I a I a h hisZ Q I a I a I a I a hBP Z Q iQ
y Q a I a I a I a h thaZ Q I a I a I a Ih ButZ Q a I a I a I a fhu fZf Q iQ g S Q a I a I a I a hsaidZ Q I a I a I a I a hshe Z Q I a I a I a I a hAnd Z Q TZBX b
これにはいくつかの空白文字が含まれているため、すべてのタブ文字→
をすべての改行なしスペース文字(コード255)に置き換えた場合のコードは*
次のとおりです。
j XI a I a I a jbZ→Q fiQ Gf a f→Q I a I a I a I a h hisZ→Q I a I a I a I a hBP Z→Q iQ →→y →Q a I a I a I a h thaZ→Q I a I a I a Ih ButZ→Q a I a I a I a fhu fZf→Q iQ g→S →Q a I a I a I a hsaidZ→Q I a I a I a I a hshe Z→Q I a I a I a I a hAnd Z→Q TZBX*b*
Hexdump:
6a 20 58 49 20 61 20 49 20 61 20 49 20 61 20 6a
62 5a 09 51 20 66 69 51 20 47 66 20 61 20 66 09
51 20 49 20 61 20 49 20 61 20 49 20 61 20 49 20
61 20 68 20 68 69 73 5a 09 51 20 49 20 61 20 49
20 61 20 49 20 61 20 49 20 61 20 68 42 50 20 20
5a 09 51 20 69 51 20 09 09 79 20 09 51 20 20 61
20 49 20 61 20 49 20 61 20 49 20 61 20 68 20 74
68 61 5a 09 51 20 49 20 61 20 49 20 61 20 49 20
61 20 49 68 20 42 75 74 5a 09 51 20 20 61 20 49
20 61 20 49 20 61 20 49 20 61 20 66 68 75 20 66
5a 66 09 51 20 69 51 20 67 09 53 20 09 51 20 20
61 20 49 20 61 20 49 20 61 20 49 20 61 20 68 73
61 69 64 5a 09 51 20 49 20 61 20 49 20 61 20 49
20 61 20 49 20 61 20 68 73 68 65 20 5a 09 51 20
49 20 61 20 49 20 61 20 49 20 61 20 49 20 61 20
68 41 6e 64 20 5a 09 51 20 54 5a 42 58 ff 62 ff
仕組みについての説明:
便利な手順は次のとおりです。
push imm8
、push imm16
およびpush imm32
に続き、pop
定数を生成します。これはah
、バイト(imm8
)をプッシュするときにゼロ(in )を生成することもできます。
and [ecx+32], ah
-ah = 0と仮定すると、バイトがゼロに設定されます。出力文字列の長さが32であるため、コードが最後から最初までバッファを埋めます。
or [ecx+32], edx
-出力バイトがゼロに設定されていると仮定すると、出力にコピーedx
(4バイト)されます。出力バッファを超えて書き込むべきではないため、バッファの終わり近くではdx
なくバリアントを使用しますedx
。コードの制限により、この方法で1バイトを書き込むことはできません!
imul edx, [ecx+32], whatever
-これがスクランブルの主なアイデアです。十分なエントロピー[ecx+32]
と数があれば、どんな出力も生成できます。必要な値の2または3バイトを生成するために使用します。複雑な点としては、出力に書き込むときに、OR
すでに存在するものすべてに対して論理的な処理を行う必要があります。これにより、メモリを再度ゼロにすることが必要になる場合がありました。
jmp
命令のバリアントを使用して戻ります。エンコーディングが0xff
であるため、これを選択しました。これは、コードページ437の改行なしスペースに対応します。
アセンブリソースコードと、それを実行するCプログラム(Visual Studio構文を使用):
#include <stdio.h>
__declspec(naked) void __fastcall doit(char* buf)
{
__asm {
push ' '
pop eax
dec ecx
and [ecx+32], ah // terminating 0 byte
dec ecx
and [ecx+32], ah
dec ecx
and [ecx+32], ah
push 98
pop edx
or [ecx+32], edx
imul dx, [ecx+32], 26183
and [ecx+32], ah
or [ecx+32], dx // two bytes: [.']
dec ecx
and [ecx+32], ah
dec ecx
and [ecx+32], ah
dec ecx
and [ecx+32], ah
dec ecx
and [ecx+32], ah
push 'sih '
pop edx
or [ecx+32], edx // 4 bytes: [ his]
dec ecx
and [ecx+32], ah
dec ecx
and [ecx+32], ah
dec ecx
and [ecx+32], ah
dec ecx
and [ecx+32], ah
push 538988610
pop edx
or [ecx+32], edx
imul edx, [ecx+32], 544803081
or [ecx+32], edx // 1 junk byte and 3 good bytes: (t's)
and [ecx+32], ah
dec ecx
and [ecx+32], ah
dec ecx
and [ecx+32], ah
dec ecx
and [ecx+32], ah
push 'aht '
pop edx
or [ecx+32], edx // 4 bytes: [ tha]
dec ecx
and [ecx+32], ah
dec ecx
and [ecx+32], ah
dec ecx
and [ecx+32], ah
dec ecx
push 'tuB '
pop edx
or [ecx+32], edx // 1 junk byte and 3 good bytes: [But]
and [ecx+32], ah
dec ecx
and [ecx+32], ah
dec ecx
and [ecx+32], ah
dec ecx
and [ecx+32], ah
push word ptr 8309
pop dx
or [ecx+32], dx
imul edx, [ecx+32], 542312807
or [ecx+32], edx // 1 junk byte and 3 good bytes: [, ']
and [ecx+32], ah
dec ecx
and [ecx+32], ah
dec ecx
and [ecx+32], ah
dec ecx
and [ecx+32], ah
push 'dias'
pop edx
or [ecx+32], edx // 4 bytes: [said]
dec ecx
and [ecx+32], ah
dec ecx
and [ecx+32], ah
dec ecx
and [ecx+32], ah
dec ecx
and [ecx+32], ah
push ' ehs'
pop edx
or [ecx+32], edx // 4 bytes: [she ]
dec ecx
and [ecx+32], ah
dec ecx
and [ecx+32], ah
dec ecx
and [ecx+32], ah
dec ecx
and [ecx+32], ah
push ' dnA'
pop edx
or [ecx+32], edx // 4 bytes: [And ]
push esp
pop edx
inc edx
pop eax
jmp dword ptr[edx-1]
}
}
int main()
{
char buf[100];
doit(buf);
puts(buf);
}