文字列と配列とポインタの逆アセンブルを見てみる

文字列と配列とポインタの逆アセンブルを見てみた。ポインタに関してはデバッガでメモリ内のデータの動きを追ってみた。

文字列

ソースコード

#include <stdio.h>

int main(void)
{
	char str[] = "Hello World";

	printf("%s\n", str);

	return 0;
}


コンパイル
gcc string_test.c -o string_test.out -fno-pie -fno-stack-protector -m32

実行結果

$ ./string_test.out 
Hello World


逆アセンブルを出力
objdump -d -M intel string_test.out

0804841d <main>:
 804841d:	55                   	push   ebp
 804841e:	89 e5                	mov    ebp,esp
 8048420:	83 e4 f0             	and    esp,0xfffffff0
 8048423:	83 ec 20             	sub    esp,0x20
 8048426:	c7 44 24 14 48 65 6c 	mov    DWORD PTR [esp+0x14],0x6c6c6548 ; 'lleH'
 804842d:	6c 
 804842e:	c7 44 24 18 6f 20 57 	mov    DWORD PTR [esp+0x18],0x6f57206f ; 'oW o'
 8048435:	6f 
 8048436:	c7 44 24 1c 72 6c 64 	mov    DWORD PTR [esp+0x1c],0x646c72 ; 'dlr' 
 804843d:	00 
 804843e:	8d 44 24 14          	lea    eax,[esp+0x14] ; 'load "Hello World" to eax'
 8048442:	89 04 24             	mov    DWORD PTR [esp],eax
 8048445:	e8 a6 fe ff ff       	call   80482f0 <puts@plt>
 804844a:	b8 00 00 00 00       	mov    eax,0x0
 804844f:	c9                   	leave  
 8048450:	c3                   	ret    
 8048451:	66 90                	xchg   ax,ax
 8048453:	66 90                	xchg   ax,ax
 8048455:	66 90                	xchg   ax,ax
 8048457:	66 90                	xchg   ax,ax
 8048459:	66 90                	xchg   ax,ax
 804845b:	66 90                	xchg   ax,ax
 804845d:	66 90                	xchg   ax,ax
 804845f:	90                   	nop

配列

ソースコード

#include <stdio.h>

int main(void)
{
	int i;
	int array[5] = {1, 2, 3, 4, 5};

	for (i = 0; i < 5; i++) {
		printf("%d\n", array[i]);
	}

	return 0;
}

コンパイル
gcc array_test.c -o array_test.out -fno-pie -fno-stack-protector -m32

実行結果

$ ./array_test.out 
1
2
3
4
5


逆アセンブルを出力
objdump -d -M intel array_test.out

0804841d <main>:
 804841d:	55                   	push   ebp
 804841e:	89 e5                	mov    ebp,esp
 8048420:	83 e4 f0             	and    esp,0xfffffff0
 8048423:	83 ec 30             	sub    esp,0x30
 8048426:	c7 44 24 18 01 00 00 	mov    DWORD PTR [esp+0x18],0x1
 804842d:	00 
 804842e:	c7 44 24 1c 02 00 00 	mov    DWORD PTR [esp+0x1c],0x2
 8048435:	00 
 8048436:	c7 44 24 20 03 00 00 	mov    DWORD PTR [esp+0x20],0x3
 804843d:	00 
 804843e:	c7 44 24 24 04 00 00 	mov    DWORD PTR [esp+0x24],0x4
 8048445:	00 
 8048446:	c7 44 24 28 05 00 00 	mov    DWORD PTR [esp+0x28],0x5
 804844d:	00 
 804844e:	c7 44 24 2c 00 00 00 	mov    DWORD PTR [esp+0x2c],0x0
 8048455:	00 
 8048456:	eb 1d                	jmp    8048475 <main+0x58>
 8048458:	8b 44 24 2c          	mov    eax,DWORD PTR [esp+0x2c] ; 'esp+0x2c is an iterator'
 804845c:	8b 44 84 18          	mov    eax,DWORD PTR [esp+eax*4+0x18]
 8048460:	89 44 24 04          	mov    DWORD PTR [esp+0x4],eax
 8048464:	c7 04 24 20 85 04 08 	mov    DWORD PTR [esp],0x8048520
 804846b:	e8 80 fe ff ff       	call   80482f0 <printf@plt>
 8048470:	83 44 24 2c 01       	add    DWORD PTR [esp+0x2c],0x1 ; 'increment iterator'
 8048475:	83 7c 24 2c 04       	cmp    DWORD PTR [esp+0x2c],0x4 ; 'check if iterator reached 4. If yes exit the function, if no continue loop'
 804847a:	7e dc                	jle    8048458 <main+0x3b>
 804847c:	b8 00 00 00 00       	mov    eax,0x0
 8048481:	c9                   	leave  
 8048482:	c3                   	ret    
 8048483:	66 90                	xchg   ax,ax
 8048485:	66 90                	xchg   ax,ax
 8048487:	66 90                	xchg   ax,ax
 8048489:	66 90                	xchg   ax,ax
 804848b:	66 90                	xchg   ax,ax
 804848d:	66 90                	xchg   ax,ax
 804848f:	90                   	nop

ポインタ

ソースコード

#include <stdio.h>

int main(void)
{
	int original_data = 1000;
	int *my_pointer;
	my_pointer = &original_data;

	printf("%d\n", *my_pointer);

	return 0;
}

コンパイル
gcc pointer_test.c -o pointer_test.out -fno-pie -fno-stack-protector -m32

実行結果

$ ./pointer_test.out 
1000


逆アセンブルを出力
objdump -d -M intel pointer_test.out

0804841d <main>:
 804841d:	55                   	push   ebp
 804841e:	89 e5                	mov    ebp,esp
 8048420:	83 e4 f0             	and    esp,0xfffffff0
 8048423:	83 ec 20             	sub    esp,0x20
 8048426:	c7 44 24 18 e8 03 00 	mov    DWORD PTR [esp+0x18],0x3e8 ; 'copy 1000 to the memory address specified by esp+0x18'
 804842d:	00 
 804842e:	8d 44 24 18          	lea    eax,[esp+0x18] ; 'load the memory address specified by esp+0x18 to EAX. esp+0x18 stores 1000 hence EAX register will point to 1000'
 8048432:	89 44 24 1c          	mov    DWORD PTR [esp+0x1c],eax ; 'copy the memory address stored at EAX (which is a pointer to 1000) to the memory address specified by esp+0x1c'
 8048436:	8b 44 24 1c          	mov    eax,DWORD PTR [esp+0x1c] ; 'copy value at esp+0x1c (which is a pointer to 1000) to EAX'
 804843a:	8b 00                	mov    eax,DWORD PTR [eax] ; 'copy the value pointed by EAX to EAX. EAX is a pointer to 1000. This instruction will copy the actual value 1000 to EAX'
 804843c:	89 44 24 04          	mov    DWORD PTR [esp+0x4],eax ; 'copy 1000 to the memory address specified by esp+0x4'
 8048440:	c7 04 24 f0 84 04 08 	mov    DWORD PTR [esp],0x80484f0 ; 'copy "%d\n" to esp'
 8048447:	e8 a4 fe ff ff       	call   80482f0 <printf@plt>
 804844c:	b8 00 00 00 00       	mov    eax,0x0
 8048451:	c9                   	leave  
 8048452:	c3                   	ret    
 8048453:	66 90                	xchg   ax,ax
 8048455:	66 90                	xchg   ax,ax
 8048457:	66 90                	xchg   ax,ax
 8048459:	66 90                	xchg   ax,ax
 804845b:	66 90                	xchg   ax,ax
 804845d:	66 90                	xchg   ax,ax
 804845f:	90                   	nop


デバッグしながらメモリ内のデータを確認してみる

8048426:	c7 44 24 18 e8 03 00 	mov    DWORD PTR [esp+0x18],0x3e8 ; 'copy 1000 to the memory address specified by esp+0x18'
Breakpoint 3, 0x0804842e in main ()
(gdb) x/x $esp+0x18
0xffffd0b8:	0x000003e8

アドレスesp+0x18に値0x3e8 (1000)がコピーされた。

 804842e:	8d 44 24 18          	lea    eax,[esp+0x18] ; 'load the memory address specified by esp+0x18 to EAX. esp+0x18 stores 1000 hence EAX register will point to 1000'
(gdb) i r
eax            0x1	1
ecx            0xacd87d2d	-1395098323
edx            0xffffd0f4	-12044
ebx            0xf7fb4000	-134529024
esp            0xffffd0a0	0xffffd0a0

ESPのアドレスは0xffffd0a0。よってesp+0x18のアドレスは0xffffd0a0 + 0x180xffffd0b8となる。

(gdb) ni
0x08048432 in main ()
(gdb) i r
eax            0xffffd0b8	-12104
ecx            0xe4cd748d	-456297331
edx            0xffffd0f4	-12044
ebx            0xf7fb4000	-134529024
esp            0xffffd0a0	0xffffd0a0
ebp            0xffffd0c8	0xffffd0c8
esi            0x0	0
edi            0x0	0
eip            0x8048432	0x8048432 <main+21>
eflags         0x286	[ PF SF IF ]
cs             0x23	35
ss             0x2b	43
ds             0x2b	43
es             0x2b	43
fs             0x0	0
gs             0x63	99
(gdb) x/x $eax
0xffffd0b8:	0x000003e8

EAXにesp+0x18のアドレス0xffffd0b8がコピーされた。アドレス0xffffd0b8には値0x3e8 (1000)が格納されている。これによりEAXは値0x3e8 (1000)をポイントするようになった。

  • EAXにはアドレス0xffffd0b8が格納されている → アドレス0xffffd0b8には値0x3e8 (1000)が格納されている

 8048432:	89 44 24 1c          	mov    DWORD PTR [esp+0x1c],eax ; 'copy the memory address stored at EAX (which is a pointer to 1000) to the memory address specified by esp+0x1c'
(gdb) i r
eax            0xffffd0b8	-12104
ecx            0xacd87d2d	-1395098323
edx            0xffffd0f4	-12044
ebx            0xf7fb4000	-134529024
esp            0xffffd0a0	0xffffd0a0
ebp            0xffffd0c8	0xffffd0c8
esi            0x0	0
edi            0x0	0
eip            0x8048436	0x8048436 <main+25>
eflags         0x286	[ PF SF IF ]
cs             0x23	35
ss             0x2b	43
ds             0x2b	43
es             0x2b	43
fs             0x0	0
gs             0x63	99
(gdb) x/x $esp+0x1c
0xffffd0bc:	0xffffd0b8

EAXに格納されているアドレス0xffffd0b8esp+0x1cにコピーされた。

8048436:	8b 44 24 1c          	mov    eax,DWORD PTR [esp+0x1c] ; 'copy value at esp+0x1c (which is a pointer to 1000) to EAX'
(gdb) x/x $eax
0xffffd0b8:	0x000003e8
(gdb) ni
0x0804843a in main ()
(gdb) x/x $eax
0xffffd0b8:	0x000003e8

esp+0x1cからEAXにアドレス0xffffd0b8がコピーされた。アドレス0xffffd0b8には値0x3e8 (1000)が格納されている。

 804843a:	8b 00                	mov    eax,DWORD PTR [eax] ; 'copy the value pointed by EAX to EAX. EAX is a pointer to 1000. This instruction will copy the actual value 1000 to EAX'
Breakpoint 1, 0x0804843a in main ()
(gdb) i r
eax            0xffffd0b8	-12104
ecx            0xdecf3cd5	-556843819
edx            0xffffd0f4	-12044
ebx            0xf7fb4000	-134529024
esp            0xffffd0a0	0xffffd0a0
ebp            0xffffd0c8	0xffffd0c8
esi            0x0	0
edi            0x0	0
eip            0x804843a	0x804843a <main+29>
eflags         0x286	[ PF SF IF ]
cs             0x23	35
ss             0x2b	43
ds             0x2b	43
es             0x2b	43
fs             0x0	0
gs             0x63	99
(gdb) x/x $eax
0xffffd0b8:	0x000003e8

mov eax,DWORD PTR [eax] 実行前のレジスタ及びメモリの状態。EAXにはアドレス0xffffd0b8が格納されている。このアドレスは値0x3e8 (1000)をポイントしている。

(gdb) ni
0x0804843c in main ()
(gdb) i r
eax            0x3e8	1000
ecx            0xdecf3cd5	-556843819
edx            0xffffd0f4	-12044
ebx            0xf7fb4000	-134529024
esp            0xffffd0a0	0xffffd0a0
ebp            0xffffd0c8	0xffffd0c8
esi            0x0	0
edi            0x0	0
eip            0x804843c	0x804843c <main+31>
eflags         0x286	[ PF SF IF ]
cs             0x23	35
ss             0x2b	43
ds             0x2b	43
es             0x2b	43
fs             0x0	0
gs             0x63	99
(gdb) x/x $eax
0x3e8:	Cannot access memory at address 0x3e8
(gdb) p $eax
$1 = 1000

mov eax,DWORD PTR [eax] 実行後のレジスタ及びメモリの状態。アドレス0xffffd0b8から値0x3e8 (1000)がEAXにコピーされた。mov命令実行前はEAXには0x3e8 (1000)を指しているアドレス0xffffd0b8が格納されていたが、mov命令実行後は0x3e8 という値そのものがEAXにコピーされた。

804843c:	89 44 24 04          	mov    DWORD PTR [esp+0x4],eax ; 'copy 1000 to the memory address specified by esp+0x4'
(gdb) ni
0x08048440 in main ()
(gdb) x/x $esp+0x4
0xffffd0a4:	0x000003e8

esp+0x4に値0x3e8 (1000)がコピーされた。

 8048440:	c7 04 24 f0 84 04 08 	mov    DWORD PTR [esp],0x80484f0 ; 'copy "%d\n" to esp'
 8048447:	e8 a4 fe ff ff       	call   80482f0 <printf@plt>
(gdb) ni
0x08048447 in main ()
(gdb) x/s 0x80484f0
0x80484f0:	"%d\n"

アドレス0x80484f0には書式文字列と改行 %d\nが格納されていた。


参考
Learning Malware Analysis (By Monnappa K A) P.112 - 114
Practical Malware Analysis (by Michael Sikorski and Andrew Honig) P.73 - 74

Leave a Reply

Your email address will not be published. Required fields are marked *