作品集(SECCON2020 第1回 SECCONバイナリ駄洒落コンテストへの応募作品)

作品一覧

■ 真のゴミプログラム(作者:坂井弘亮)

08048054 <_start>:
 8048054:       e8 00 00 00 00          call   8048059 <_start+0x5>
 8048059:       59                      pop    %ecx
 804805a:       8b 59 04                mov    0x4(%ecx),%ebx
 804805d:       53                      push   %ebx
 804805e:       53                      push   %ebx
 804805f:       53                      push   %ebx
 8048060:       53                      push   %ebx
 8048061:       c3                      ret
上は,x86で動作するゴミプログラムの逆アセンブリです.

push EBX(0x53:ゴミ)でゴミデータをpushするだけのゴミ命令が埋め込まれており, その機械語コードをEBXにロードすることでEBXに0x53535353(ゴミゴミゴミゴミ) というゴミデータを入れ,ゴミ命令によってゴミデータでスタックを埋め, 最後にretすると0x53535353というゴミアドレスに戻ろうとすることで セグメンテーションフォルトとなりゴミのようなコアダンプを吐くという, まさにゴミプログラムです.

出力されたコアダンプを逆アセンブルして見てみると,スタックがゴミで埋まって おり,まさにゴミプログラムという点が, 駄洒落にふさわしいと言えるでしょう.

...
bfbfe650:       53                      push   %ebx
bfbfe651:       53                      push   %ebx
bfbfe652:       53                      push   %ebx
bfbfe653:       53                      push   %ebx
bfbfe654:       53                      push   %ebx
bfbfe655:       53                      push   %ebx
bfbfe656:       53                      push   %ebx
bfbfe657:       53                      push   %ebx
bfbfe658:       53                      push   %ebx
bfbfe659:       53                      push   %ebx
bfbfe65a:       53                      push   %ebx
bfbfe65b:       53                      push   %ebx
bfbfe65c:       53                      push   %ebx
bfbfe65d:       53                      push   %ebx
bfbfe65e:       53                      push   %ebx
bfbfe65f:       53                      push   %ebx
...

■ 不死のプログラム(作者:坂井弘亮)

/* for Linux/x86 (not amd64) */

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

int halt(void)
{
  asm volatile ("hlt");
}

struct sigframe {
  int pretcode;
  int sig;
  struct sigcontext sc;
};

void sighandler(int val)
{
  long *sp;
  unsigned char *pc;
  volatile struct sigframe *frame;

  sp = __builtin_frame_address(0);
  frame = (struct sigframe *)(sp + 1);
  pc = (unsigned char *)frame->sc.eip;

  if (*pc == 0xf4) {
    frame->sc.eip = (long)(pc + 1);
    return;
  }

  exit(0);
}

int main(void)
{
  signal(SIGSEGV, sighandler);
  halt();
  write(1, "OK\n", 3);
  return 0;
}
上は,Linux/x86で動作する不死身のプログラムです.

hlt命令を呼び出しており,通常はここで Segmentation fault で実行停止しますが SIGSEGVをハンドリングしてhlt命令の場合にはプログラムカウンタを進めて復帰し hlt命令を読み飛ばすことで,不死のプログラムになっています.

実行結果は以下です.

$ ./virtual-halt
OK
以下はhalt()の逆アセンブル結果です.
08048424 <halt>:
 8048424:       55                      push   %ebp
 8048425:       89 e5                   mov    %esp,%ebp
 8048427:       f4                      hlt
 8048428:       5d                      pop    %ebp
 8048429:       c3                      ret
hlt命令の機械語コードが0xf4(不死)であり,プログラムの不死の動作に掛け合わせて いるところが,この駄洒落の面白いところです.

■ SECCONよろしく!(作者:坂井弘亮)

	.section .text

	.globl	_start
	.type	_start, @function
_start:
	mov	$yorosiku, %eax
	lea	8(%eax), %ecx
	mov	$0, %esi
	mov	$4, %eax
	mov	$1, %ebx
	mov	$4, %edx

1:	inc	%esi	/* 0x46 */
	dec	%ecx	/* 0x49 */
	inc	%esi	/* 0x46 */
	dec	%ecx	/* 0x49 */
	dec	%ecx	/* 0x49 */
	inc	%esi	/* 0x46 */
	dec	%ecx	/* 0x49 */
	inc	%esi	/* 0x46 */

	int	$0x80

	cmp	$8, %esi
	jne	1b

	mov	$1, %eax
	mov	$0, %ebx
	int	$0x80

yorosiku:
	.string	"sikuyoro"
上は,Linux/x86で動作するプログラムです.
以下がその逆アセンブル結果です.
08048098 <_start>:
 8048098:       b8 cf 80 04 08          mov    $0x80480cf,%eax
 804809d:       8d 48 08                lea    0x8(%eax),%ecx
 80480a0:       be 00 00 00 00          mov    $0x0,%esi
 80480a5:       b8 04 00 00 00          mov    $0x4,%eax
 80480aa:       bb 01 00 00 00          mov    $0x1,%ebx
 80480af:       ba 04 00 00 00          mov    $0x4,%edx
 80480b4:       46                      inc    %esi
 80480b5:       49                      dec    %ecx
 80480b6:       46                      inc    %esi
 80480b7:       49                      dec    %ecx
 80480b8:       49                      dec    %ecx
 80480b9:       46                      inc    %esi
 80480ba:       49                      dec    %ecx
 80480bb:       46                      inc    %esi
 80480bc:       cd 80                   int    $0x80
 80480be:       83 fe 08                cmp    $0x8,%esi
 80480c1:       75 f1                   jne    80480b4 <_start+0x1c>
 80480c3:       b8 01 00 00 00          mov    $0x1,%eax
 80480c8:       bb 00 00 00 00          mov    $0x0,%ebx
 80480cd:       cd 80                   int    $0x80

080480cf <yorosiku>:
 80480cf:       73 69                   jae    804813a <yorosiku+0x6b>
 80480d1:       6b 75 79 6f             imul   $0x6f,0x79(%ebp),%esi
 80480d5:       72 6f                   jb     8048146 <yorosiku+0x77>
以下が実行結果です.
$ ./yorosiku
yorosiku
プログラム中では inc ESI, dec ECX の機械語コードがそれぞれ 0x46, 0x49 であり, これらの連続が「よろしくよろしく」となっています.
またESIをインクリメントすることでループカウンタ,ECXをデクリメントすることで 表示位置を指しており,実際にESI/ECXの値を利用して表示処理を行っています.

このため「よろしく」という命令を「よろしくよろしく...」と繰り返し実行することで 「yorosiku」という文字列を実際に表示している点が掛け合わされており, そこがこの駄洒落の面白さです.

さらに表示文字列のデータは「しくよろ」となっており,また inc / dec による 機械語コードも途中から「しくよろしくよろ」という若者言葉になっていて,駄洒落を 中高年のものとして敬遠しがちな 若者にも馴染みやすい駄洒落となっています.

■ 俺!俺!(作者:坂井弘亮)

 00 11 22 33  44 55 00 66  77 88 99 AA  08 00 45 00
 00 54 D4 9D  00 00 40 01  22 B8 C0 A8  01 02 C0 A8
 01 01*00*00* 2A 18 A7 04  00 00 53 9B  9F 77 00 06
 50 C7 08 09  0A 0B 0C 0D  0E 0F 10 11  12 13 14 15
 16 17 18 19  1A 1B 1C 1D  1E 1F 20 21  22 23 24 25
 26 27 28 29  2A 2B 2C 2D  2E 2F 30 31  32 33 34 35
 36 37
上は,ICMP Echo Reply のパケットである.

ICMPヘッダの type と code の部分(上記*の部分)が 00 00 となっており 「俺!俺!」と言っている.
ICMP Echo による存在問い合わせに対して,自分はいるよと応答している様が type と code に掛け合っており, そこがこの駄洒落の面白い点です.


メールは kozos(アットマーク)kozos.jp まで