Ethereum的可靠文件说:
EVM虚拟机(EVM)是Ethereum中智能契约的运行时环境。它不仅是沙箱的,而且实际上是完全隔离的,这意味着在EVM中运行的代码无法访问网络、文件系统或其他进程。
限制对网络、文件系统和其他进程的访问是否足以防止图灵完整语言脱离沙箱?
发布于 2016-03-23 08:31:00
逃避沙箱不是在语言上,而是在实现上。我看到了以下VM实现:
每个实现都依赖于编译器/解释器的正确性和实现本身的正确性。攻击者可能想要逃离Ethereum,为了实现这一点,他必须利用编译器/解释器/标准库以及实现本身中的一些bug。虽然这是一项艰巨的任务,但这绝不是不可能的(很可能,涉及零日)。我认为libethereum是在C++中实现的最脆弱的.
几年后,随着Ethereum被接受,将出现一个占主导地位的实现,它将使攻击者的任务更容易(网三伞具有规范的可靠编译器)。
为了在这样的攻击中提供深入的防御,人们建议在普通的越野车内运行Ethereum沙箱.即使如此,防止攻击的主要方法仍将依靠手工检查合同:
注意:在这个阶段,两种图灵全语言( Serpent)和几十个编译器版本(60+ Solidity遗留版本)的存在使得维护者更难以检测恶意契约。
发布于 2016-03-23 09:34:45
不,不,它不是,它是相当复杂的预防。
沙盒通常挂起内部API并在第3环中的最低级别执行代码。让我们首先谈谈文件API。如果您熟悉较低级别的编程语言(如C、C++等),您将了解ReadFile API。那么,让我们看看反汇编中的ReadFile。
ReadFile位于Kernel32中的EAT (Export表)中。
KERNEL32.ReadFile - FF 25 8803D674 - jmp dword ptr [KERNEL32.PssWalkSnapshot+9588] { ->KERNELBASE.ReadFile }因此,它跳到KernelBase.dll到一个ReadFile。不要担心不理解所有的操作码,而只是对电话感兴趣。
KERNELBASE.ReadFile - 8B FF - mov edi,edi
KERNELBASE.ReadFile+2- 55 - push ebp
KERNELBASE.ReadFile+3- 8B EC - mov ebp,esp
KERNELBASE.ReadFile+5- 6A FE - push -02 { 254 }
KERNELBASE.ReadFile+7- 68 A806D576 - push KERNELBASE.ReadFile+B8 { [FFFFFFFE] }
KERNELBASE.ReadFile+C- 68 5098D576 - push KERNELBASE.OutputDebugStringA+C0 { [8B55FF8B] }
KERNELBASE.ReadFile+11- 64 A1 00000000 - mov eax,fs:[00000000] { 0 }
KERNELBASE.ReadFile+17- 50 - push eax
KERNELBASE.ReadFile+18- 83 EC 18 - sub esp,18 { 24 }
KERNELBASE.ReadFile+1B- 53 - push ebx
KERNELBASE.ReadFile+1C- 56 - push esi
KERNELBASE.ReadFile+1D- 57 - push edi
KERNELBASE.ReadFile+1E- A1 683BE076 - mov eax,[KERNELBASE.dll+C3B68] { [1EB677D9] }
KERNELBASE.ReadFile+23- 31 45 F8 - xor [ebp-08],eax
KERNELBASE.ReadFile+26- 33 C5 - xor eax,ebp
KERNELBASE.ReadFile+28- 50 - push eax
KERNELBASE.ReadFile+29- 8D 45 F0 - lea eax,[ebp-10]
KERNELBASE.ReadFile+2C- 64 A3 00000000 - mov fs:[00000000],eax { 0 }
KERNELBASE.ReadFile+32- 89 65 E8 - mov [ebp-18],esp
KERNELBASE.ReadFile+35- C7 45 E0 00000000 - mov [ebp-20],00000000 { 0 }
KERNELBASE.ReadFile+3C- C7 45 E4 00000000 - mov [ebp-1C],00000000 { 0 }
KERNELBASE.ReadFile+43- 8B 75 14 - mov esi,[ebp+14]
KERNELBASE.ReadFile+46- 85 F6 - test esi,esi
KERNELBASE.ReadFile+48- 74 06 - je KERNELBASE.ReadFile+50
KERNELBASE.ReadFile+4A- C7 06 00000000 - mov [esi],00000000 { 0 }
KERNELBASE.ReadFile+50- 8B 5D 08 - mov ebx,[ebp+08]
KERNELBASE.ReadFile+53- 83 FB F4 - cmp ebx,-0C { 244 }
KERNELBASE.ReadFile+56- 0F83 60D30400 - jae KERNELBASE.InterlockedExchangeAdd+528C
KERNELBASE.ReadFile+5C- 8B 7D 18 - mov edi,[ebp+18]
KERNELBASE.ReadFile+5F- 85 FF - test edi,edi
KERNELBASE.ReadFile+61- 75 71 - jne KERNELBASE.ReadFile+D4
KERNELBASE.ReadFile+63- 57 - push edi
KERNELBASE.ReadFile+64- 57 - push edi
KERNELBASE.ReadFile+65- FF 75 10 - push [ebp+10]
KERNELBASE.ReadFile+68- FF 75 0C - push [ebp+0C]
KERNELBASE.ReadFile+6B- 8D 45 E0 - lea eax,[ebp-20]
KERNELBASE.ReadFile+6E- 50 - push eax
KERNELBASE.ReadFile+6F- 57 - push edi
KERNELBASE.ReadFile+70- 57 - push edi
KERNELBASE.ReadFile+71- 57 - push edi
KERNELBASE.ReadFile+72- 53 - push ebx
KERNELBASE.ReadFile+73- FF 15 5C66E076 - call dword ptr [KERNELBASE.dll+C665C] { ->ntdll.NtReadFile }
KERNELBASE.ReadFile+79- 8B C8 - mov ecx,eax
KERNELBASE.ReadFile+7B- 81 F9 03010000 - cmp ecx,00000103 { 259 }
KERNELBASE.ReadFile+81- 0F84 B9D30400 - je KERNELBASE.InterlockedExchangeAdd+5310
KERNELBASE.ReadFile+87- 85 C9 - test ecx,ecx
KERNELBASE.ReadFile+89- 0F88 380A0000 - js KERNELBASE.GetModuleHandleExW+277
KERNELBASE.ReadFile+8F- 85 F6 - test esi,esi
KERNELBASE.ReadFile+91- 74 05 - je KERNELBASE.ReadFile+98
KERNELBASE.ReadFile+93- 8B 45 E4 - mov eax,[ebp-1C]
KERNELBASE.ReadFile+96- 89 06 - mov [esi],eax
KERNELBASE.ReadFile+98- B8 01000000 - mov eax,00000001 { 1 }
KERNELBASE.ReadFile+9D- 8B 4D F0 - mov ecx,[ebp-10]
KERNELBASE.ReadFile+A0- 64 89 0D 00000000 - mov fs:[00000000],ecx { 0 }
KERNELBASE.ReadFile+A7- 59 - pop ecx
KERNELBASE.ReadFile+A8- 5F - pop edi
KERNELBASE.ReadFile+A9- 5E - pop esi
KERNELBASE.ReadFile+AA- 5B - pop ebx
KERNELBASE.ReadFile+AB- 8B E5 - mov esp,ebp
KERNELBASE.ReadFile+AD- 5D - pop ebp
KERNELBASE.ReadFile+AE- C2 1400 - ret 0014 { 20 }因此,下一级API是位于NtReadFile中的ntdll.dll。
ntdll.NtReadFile - B8 05001A00 - mov eax,001A0005 { [0] }
ntdll.ZwReadFile+5- 64 FF 15 C0000000 - call fs:[000000C0]
ntdll.ZwReadFile+C- C2 2400 - ret 0024 { 36 }
ntdll.ZwReadFile+F- 90 - nop 这是一种特殊类型的调用,名为syscall,然后转到SSDT (System Service Descriptor Table),它具有位于0环中的低级API,该API不能通过暴露的syscall以外的环3直接访问。
因此,沙箱可以使用一系列挂钩方法,但最常见的方法是:
所以,为了知道发生了什么,我们会将NtReadFile连接起来,这将跳转到我们的代码中,并且我们可以完全控制执行的内容。例如,假设您要过滤掉任何名为SteveEnix的文件。在我们的蹦床函数中( NtReadFile已经被钩住并跳转到其中),我们可以读取参数并决定是否调用它。所以,看起来是这样的:
NTSYSAPI NTSTATUS NTAPI t_NtReadFile(
IN HANDLE FileHandle,
IN HANDLE Event OPTIONAL,
IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
IN PVOID ApcContext OPTIONAL,
OUT PIO_STATUS_BLOCK IoStatusBlock,
OUT PVOID Buffer,
IN ULONG Length,
IN PLARGE_INTEGER ByteOffset OPTIONAL,
IN PULONG Key OPTIONAL )
{
// Your check on buffer to filter files or whatever you want and return an error or call the original function
}如果内部应用程序可以访问使用VirtualProtect API,或者读取和写入内存区域,那么这些钩子就可以很容易地删除。
但是,如果您更进一步到SSDT (在x64上有PatchGuard以防止这些钩子),那么沙箱通常不会接触SSDT,那么您需要一个驱动程序来加载到系统中,以便能够解除SSDT的补丁或用自己的钩子修补它。
https://security.stackexchange.com/questions/118268
复制相似问题