こんばんわ。id:TAKESAKOです。
連日の投稿になってしまいますが、せっかく前日に80386のプログラミングテクニックを覚えたので、
Win32 Trackに対抗して、Borland C++ 5.5 Compilerで記号プログラミングをしてみましょう。
char main[]="`%[_-]%-```%`-_-`[_][_]_[-~-%#-[,~]-#[],-][_--_[_%`________-_" "`~#--)_]-`]~`-`#-[-`]`[`]]]]]]]]),_-]_%%-,#)--)_----_%,--[%,`_]]_]][-,-)~" "--`-`-),][---~`-`-_%`][[_]][-_`[%-~%#]-~`%)-)~#---_%-`____]_]-,_%%-,~_--)" "~[,-%]])-#-]#`]_[[_[]-)%[]-)#%~-__~_-)]`~--~`[`][]][_]-%-~%-%)_%-,~[)--%#" ",--%,)`]_[[][]-`~[`-[],%-[[-#-~]-#-#--#`]__]_[]-%_,--#_~--#`,#-]~~%-[~[#`" "_[]_[_[-]]]`--~_`-))`#-~,-#-%#%#`_]_]_]]---_%---~---%_#-,[~`-,%][`_][]__]" "-]),)-~`%`-,~~`--`-`-~%~``[[_]][]-]`#]---`--,-~,-%_%)-%,%-`[[][]]]-[--%-%" "`,#-_~][-#[~#-%`~#`[][[[][-%[~--]_~#--%)_-,%#_-_`#]`[__]]__--_][-,_,~-,,~" "~-,,~_-,))``___[]]_,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,," ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,," ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,," ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,," ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,," ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,," ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,," ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,," ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,," ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,," ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,," ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,," ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,," ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,";
最後の,,,,,,,,,,,,,,,,の繰り返しは自己書き換え用のパディング領域です。sub命令なのでalレジスタの値が変わってしまいますが、2バイトコードのnop的な役割で使用しています。
WindowsXP日本語版SP2のBorland C++ 5.5 Compilerでしか動作しませんが、動きましたね。
前回と同じ原理で、以下のWindows XP SP2シェルコードがスタック上に展開されます。
00000000 31 C0 xor eax,eax 00000002 50 push eax 00000003 E8 0E 00 00 00 call label_16 00000008 48 65 6C 6C 6F db "Hello" 0000000C 2C 20 57 6F 72 db ", wor" 00000012 6C 64 21 00 dd "ld!",0 label_16: 00000016 E8 0E 00 00 00 call label_29 0000001B 41 56 54 6F 6B db "AVTok" 00000020 79 6F 20 32 30 db "yo 20" 00000025 31 30 21 00 db "10!",0 label_29: 00000029 50 push eax 0000002A B871EA3F77 mov eax,0x773fea71 ; MessageBoxA @ user32.dll 0000002F FFD0 call eax 00000031 B8EF2A2576 mov eax,0x76252aef ; ExitProcess @ kernel32.dll 00000036 FFD0 call eax
DLLの各種APIを絶対アドレスで呼び出しています。
ですよね。わかります。試験に出るので暗記しておきましょう。
インテルのx86マニュアルを見ると0x08~0x7Fの範囲のopcode表は以下の通りです。
+--+--------+--------+--------+--------+--------+--------+--------+--------+ | | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | +--+--------+--------+--------+--------+--------+--------+--------+--------+ | 0| ADD |PUSH |POP | | |mb+=rb |mw+=rw |rb+=rmb |rw+=rmw |al+=ib |ax+=iw |es |es | +--+--------+--------+--------+--------+--------+--------+--------+--------+ | 1| ADC |PUSH |POP | | |mb+=rb |mw+=rw |rb+=rmb |rw+=rmw |al+=ib |ax+=iw |ss |ss | +--+--------+--------+--------+--------+--------+--------+--------+--------+ | 2| AND | |DAA | | |mb&=rb |mw&=rw |rb&=rmb |rw&=rmw |al&=ib |ax&=iw |es: | | +--+--------+--------+--------+--------+--------+--------+--------+--------+ | 3| XOR | |AAA | | |mb^=rb |mw^=rw |rb^=rmb |rw^=rmw |al^=ib |ax^=iw |ss: | | +--+--------+--------+--------+--------+--------+--------+--------+--------+ | 4| INC | | |ax++ |cx++ |dx++ |bx++ |sp++ |bp++ |si++ |di++ | +--+--------+--------+--------+--------+--------+--------+--------+--------+ | 5| PUSH | | |ax |cx |dx |bx |sp |bp |si |di | +--+--------+--------+--------+--------+--------+--------+--------+--------+ | 6|PUSHA |POPA |BOUND |ARPL | | |Operand |Address | | | | |rw,md |rmw,rw |fs: |gs: |Size |Size | +--+--------+--------+--------+--------+--------+--------+--------+--------+ | 7|JO |JNO |JC/JB/ |JNC/JNB/|JZ/JE |JNZ/JNE |JNA/JBE |JA/JNBE | | |rs |rs |JNAE rs|JAE rs|rs |rs |rs |rs | +--+--------+--------+--------+--------+--------+--------+--------+--------+ +--+--------+--------+--------+--------+--------+--------+--------+--------+ | | 8 | 9 | A | B | C | D | E | F | +--+--------+--------+--------+--------+--------+--------+--------+--------+ | 0| OR |PUSH |2Byte | | |mb|=rb |mw|=rw |rb|=rmb |rw|=rmw |al|=ib |ax|=iw |cs |OPcode | +--+--------+--------+--------+--------+--------+--------+--------+--------+ | 1| SBB |PUSH |POP | | |mb-=rb |mw-=rw |rb-=rmb |rw-=rmw |al-=ib |ax-=iw |ds |ds | +--+--------+--------+--------+--------+--------+--------+--------+--------+ | 2| SUB | |DAS | | |mb-=rb |mw-=rw |rb-=rmb |rw-=rmw |al-=ib |ax-=iw |cs: | | +--+--------+--------+--------+--------+--------+--------+--------+--------+ | 3| CMP | |AAS | | |f=mb-rb |f=mw-rw |f=rb-rmb|f=rw-rmw|f=al-ib |f=ax-iw |ds: | | +--+--------+--------+--------+--------+--------+--------+--------+--------+ | 4| DEC | | |ax-- |cx-- |dx-- |bx-- |sp-- |bp-- |si-- |di-- | +--+--------+--------+--------+--------+--------+--------+--------+--------+ | 5| POP | | |ax |cx |dx |bx |sp |bp |si |di | +--+--------+--------+--------+--------+--------+--------+--------+--------+ | 6|PUSH |IMUL rw=|PUSH |IMUL rw=|INSB |INSW |OUTSB |OUTSW | | |iw |rmw*iw |ib |rmw*ib | | | | | +--+--------+--------+--------+--------+--------+--------+--------+--------+ | 7|JS |JNS |JP/JPE |JNP/JPO |JL/JNGE |JNL/JGE |JNG/JLE |JG/JNLE | | |rs |rs |rs |rs |rs |rs |rs |rs | +--+--------+--------+--------+--------+--------+--------+--------+--------+
ちょうど0x28~0x2Dの範囲がSUB命令の1バイト目となっていますね。
28 29 2A 2B 2C 2D ( ) * + , -
プログラムのソースをよく見るとわかるのですが、x86で使っている記号の文字が10種類しかありません。
# % ) , - [ ] _ ` ~
これらの記号をASCIIコードを数値とみなして0から引き算して数を作ってみます。
[130,160,161,163,165,211,212,215,219,221,]
[4,34,35,37,39,64,65,66,67,68,69,70,72,74,85,86,89,93,95,115,116,117,118,119, 120,121,122,123,124,125,126,128,130,166,167,168,170,171,174,175,176,177,178, 180,182,184,186,]
[0,2,4,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,37,39,40,41,42,44, 45,48,49,50,51,52,54,56,58,60,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84, 85,86,87,88,89,90,91,93,95,121,122,123,124,125,126,127,129,130,131,132,133, 134,135,136,137,138,139,140,141,142,143,145,147,149,151,164,165,167,169,194, 195,196,197,198,199,200,202,204,215,216,219,223,224,225,226,227,228,229,230, 231,232,233,234,235,237,239,245,246,247,248,249,250,251,252,253,254,255,]
[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,19,21,23,25,26,27,28,29,30,31, 32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56, 58,60,68,69,70,71,72,73,74,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91, 92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112, 113,114,116,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134, 135,136,137,138,139,140,141,142,143,144,146,148,149,150,151,152,153,154,155, 156,157,158,159,160,161,162,163,164,165,167,169,170,171,172,174,175,178,179, 180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198, 199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217, 218,219,220,221,223,225,230,231,232,233,234,235,236,237,238,239,240,241,242, 243,244,245,246,247,248,249,250,251,252,253,254,255,]
[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28, 29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54, 55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80, 81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104, 105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123, 124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142, 143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161, 162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180, 181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199, 200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218, 219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237, 238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255]
このように5回の引き算を行えば、0~255の任意の数値を作成することができます。
勘の良い人ならすぐにわかると思いますが、引き算の回数を増やせばもっと記号の種類を減らせるかもしれませんね。最後は極限の7文字まで減らした記号プログラミングを試してみたいと思います。