シェルコーディングは初めてです。アセンブリコードを記述しました。
section .text
global _start
_start:
jmp end
start:
;open file
pop ebx ; get address of filename
xor eax,eax
mov [ebx+3], al
mov al,5
xor ecx,ecx
mov edx,777
int 80h
;exit
xor eax,eax
mov al,1
mov ebx,1
int 80h
end:
call start
db "AAAA"
ただし、「sys_open」システムコールが行われているか、「strace」ツールを使用していないかを確認すると、ファイルのオープンに関連するシステムコールが表示されません。
私のシェルコードの何が問題になっていますか?
「strace」出力:
rakesh@rakesh-VirtualBox:~/shellcode$ strace ./a.out
execve("./a.out", ["./a.out"], [/* 21 vars */]) = 0
brk(0) = 0x6cf000
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f7c53efe000
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=62357, ...}) = 0
mmap(NULL, 62357, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f7c53eee000
close(3) = 0
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\240\30\2\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=1815224, ...}) = 0
mmap(NULL, 3929304, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f7c5391e000
mprotect(0x7f7c53ad3000, 2097152, PROT_NONE) = 0
mmap(0x7f7c53cd3000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1b5000) = 0x7f7c53cd3000
mmap(0x7f7c53cd9000, 17624, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f7c53cd9000
close(3) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f7c53eed000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f7c53eec000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f7c53eeb000
Arch_prctl(Arch_SET_FS, 0x7f7c53eec700) = 0
mprotect(0x7f7c53cd3000, 16384, PROT_READ) = 0
mprotect(0x600000, 4096, PROT_READ) = 0
mprotect(0x7f7c53f00000, 4096, PROT_READ) = 0
munmap(0x7f7c53eee000, 62357) = 0
fstat(1, {st_mode=03260764276, st_size=140733642434881, ...}) = 3
write(1, "\242\350\303\32\377\177\0\0\0\0\0\0\0\0\0\0\252\350\303\32\377\177\0\0\276\350\303\32\377\177\0\0"..., 777 <unfinished ... exit status 1>
私は解決策を得ました。実際、私は誤ってシェルコードテストプログラムを64ビット実行可能ファイルとしてコンパイルしました。そのため、シェルコードが64ビットモードで実行され、64ビットモードではsyscall no 5は「fstat」用であり、straceツールが表示していたものです。
-e open
に関する混乱を解消するために、この回答を編集しています。 -e
はフィルタリングのみを行い、straceログに追加情報を追加しません。 strace
がログを記録していない唯一のケースopen
syscallsは、フォークされたサブプロセスがそれらを呼び出しており、-f
パラメータが設定されていない場合です。
AMD64アーキテクチャでは、さらに新しいx86 CPUでも、システムコールはsysenter
オペコードで発生し、int 80h
では発生しません。 strace出力は、x86命令と32ビットレジスタのみを使用したにもかかわらず、コードをAMD64にコンパイルしたことを明確に示しています(32ビット以上のポインターを使用していることがわかります)。
違いは、カーネルによってユーザースペース(libvdso)にマップされた単一ページの共有ライブラリで処理されます。アプリは、通常の関数と同じように、このlibvdsoのみを呼び出す必要があります。
最小限のCコードを静的にコンパイルして逆アセンブルする場合(glibcも使用したくない場合)は、その形式を見つける最も簡単な方法です。