mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 20:42:43 +00:00 
			
		
		
		
	UserspaceEmulator: Catch use-after-frees by tracking malloc/free :^)
This patch introduces a "MallocTracer" to the UserspaceEmulator.
If this object is present on the Emulator, it can be notified whenever
the emulated program does a malloc() or free().
The notifications come in via a magic instruction sequence that we
embed in the LibC malloc() and free() functions. The sequence is:
    "salc x2, push reg32 x2, pop reg32 x3"
The data about the malloc/free operation is in the three pushes.
We make sure the sequence is harmless when running natively.
Memory accesses on MmapRegion are then audited to see if they fall
inside a known-to-be-freed malloc chunk. If so, we complain loud
and red in the debugger output. :^)
This is very, very cool! :^)
It's also a whole lot slower than before, since now we're auditing
memory accesses against a new set of metadata. This will need to be
optimized (and running in this mode should be opt-in, perhaps even
a separate program, etc.)
			
			
This commit is contained in:
		
							parent
							
								
									d7c87e84f3
								
							
						
					
					
						commit
						c314292319
					
				
					 9 changed files with 274 additions and 5 deletions
				
			
		|  | @ -1,5 +1,6 @@ | ||||||
| set(SOURCES | set(SOURCES | ||||||
|     Emulator.cpp |     Emulator.cpp | ||||||
|  |     MallocTracer.cpp | ||||||
|     MmapRegion.cpp |     MmapRegion.cpp | ||||||
|     SharedBufferRegion.cpp |     SharedBufferRegion.cpp | ||||||
|     SimpleRegion.cpp |     SimpleRegion.cpp | ||||||
|  |  | ||||||
|  | @ -66,6 +66,7 @@ Emulator::Emulator(const Vector<String>& arguments, NonnullRefPtr<ELF::Loader> e | ||||||
|     : m_elf(move(elf)) |     : m_elf(move(elf)) | ||||||
|     , m_cpu(*this) |     , m_cpu(*this) | ||||||
| { | { | ||||||
|  |     m_malloc_tracer = make<MallocTracer>(); | ||||||
|     ASSERT(!s_the); |     ASSERT(!s_the); | ||||||
|     s_the = this; |     s_the = this; | ||||||
|     setup_stack(arguments); |     setup_stack(arguments); | ||||||
|  | @ -167,12 +168,20 @@ int Emulator::exec() | ||||||
|     return m_exit_status; |     return m_exit_status; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | bool Emulator::is_in_malloc_or_free() const | ||||||
|  | { | ||||||
|  |     auto symbol = m_elf->symbolicate(m_cpu.eip()); | ||||||
|  |     return symbol.starts_with("malloc") || symbol.starts_with("free"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static pid_t s_pid = getpid(); | ||||||
|  | 
 | ||||||
| void Emulator::dump_backtrace() | void Emulator::dump_backtrace() | ||||||
| { | { | ||||||
|     u32 offset = 0; |     u32 offset = 0; | ||||||
|     String symbol = m_elf->symbolicate(m_cpu.eip(), &offset); |     String symbol = m_elf->symbolicate(m_cpu.eip(), &offset); | ||||||
| 
 | 
 | ||||||
|     printf("> %#08x  %s +%#x\n", m_cpu.eip(), symbol.characters(), offset); |     dbgprintf("==%d==    %#08x  %s +%#x\n", s_pid, m_cpu.eip(), symbol.characters(), offset); | ||||||
| 
 | 
 | ||||||
|     u32 frame_ptr = m_cpu.ebp(); |     u32 frame_ptr = m_cpu.ebp(); | ||||||
|     while (frame_ptr) { |     while (frame_ptr) { | ||||||
|  | @ -181,7 +190,7 @@ void Emulator::dump_backtrace() | ||||||
|             return; |             return; | ||||||
|         symbol = m_elf->symbolicate(ret_ptr, &offset); |         symbol = m_elf->symbolicate(ret_ptr, &offset); | ||||||
|         if (!symbol.is_null()) |         if (!symbol.is_null()) | ||||||
|             printf("> %#08x  %s +%#x\n", ret_ptr, symbol.characters(), offset); |             dbgprintf("==%d==    %#08x  %s +%#x\n", s_pid, ret_ptr, symbol.characters(), offset); | ||||||
| 
 | 
 | ||||||
|         frame_ptr = m_mmu.read32({ 0x20, frame_ptr }); |         frame_ptr = m_mmu.read32({ 0x20, frame_ptr }); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -26,6 +26,7 @@ | ||||||
| 
 | 
 | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
|  | #include "MallocTracer.h" | ||||||
| #include "SoftCPU.h" | #include "SoftCPU.h" | ||||||
| #include "SoftMMU.h" | #include "SoftMMU.h" | ||||||
| #include <AK/Types.h> | #include <AK/Types.h> | ||||||
|  | @ -35,6 +36,8 @@ | ||||||
| 
 | 
 | ||||||
| namespace UserspaceEmulator { | namespace UserspaceEmulator { | ||||||
| 
 | 
 | ||||||
|  | class MallocTracer; | ||||||
|  | 
 | ||||||
| class Emulator { | class Emulator { | ||||||
| public: | public: | ||||||
|     static Emulator& the(); |     static Emulator& the(); | ||||||
|  | @ -49,12 +52,18 @@ public: | ||||||
| 
 | 
 | ||||||
|     SoftMMU& mmu() { return m_mmu; } |     SoftMMU& mmu() { return m_mmu; } | ||||||
| 
 | 
 | ||||||
|  |     MallocTracer* malloc_tracer() { return m_malloc_tracer; } | ||||||
|  | 
 | ||||||
|  |     bool is_in_malloc_or_free() const; | ||||||
|  | 
 | ||||||
| private: | private: | ||||||
|     NonnullRefPtr<ELF::Loader> m_elf; |     NonnullRefPtr<ELF::Loader> m_elf; | ||||||
| 
 | 
 | ||||||
|     SoftMMU m_mmu; |     SoftMMU m_mmu; | ||||||
|     SoftCPU m_cpu; |     SoftCPU m_cpu; | ||||||
| 
 | 
 | ||||||
|  |     OwnPtr<MallocTracer> m_malloc_tracer; | ||||||
|  | 
 | ||||||
|     void setup_stack(const Vector<String>& arguments); |     void setup_stack(const Vector<String>& arguments); | ||||||
| 
 | 
 | ||||||
|     int virt$shbuf_create(int size, FlatPtr buffer); |     int virt$shbuf_create(int size, FlatPtr buffer); | ||||||
|  |  | ||||||
							
								
								
									
										110
									
								
								DevTools/UserspaceEmulator/MallocTracer.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										110
									
								
								DevTools/UserspaceEmulator/MallocTracer.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,110 @@ | ||||||
|  | /*
 | ||||||
|  |  * Copyright (c) 2020, Andreas Kling <kling@serenityos.org> | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions are met: | ||||||
|  |  * | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright notice, this | ||||||
|  |  *    list of conditions and the following disclaimer. | ||||||
|  |  * | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright notice, | ||||||
|  |  *    this list of conditions and the following disclaimer in the documentation | ||||||
|  |  *    and/or other materials provided with the distribution. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||||
|  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||||
|  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||||
|  |  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE | ||||||
|  |  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||||||
|  |  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | ||||||
|  |  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | ||||||
|  |  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | ||||||
|  |  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||||||
|  |  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #include "MallocTracer.h" | ||||||
|  | #include "Emulator.h" | ||||||
|  | #include <AK/LogStream.h> | ||||||
|  | 
 | ||||||
|  | namespace UserspaceEmulator { | ||||||
|  | 
 | ||||||
|  | static pid_t s_pid = getpid(); | ||||||
|  | 
 | ||||||
|  | MallocTracer::MallocTracer() | ||||||
|  | { | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void MallocTracer::target_did_malloc(Badge<SoftCPU>, FlatPtr address, size_t size) | ||||||
|  | { | ||||||
|  |     if (auto* existing_mallocation = find_mallocation(address)) { | ||||||
|  |         ASSERT(existing_mallocation->freed); | ||||||
|  |         existing_mallocation->size = size; | ||||||
|  |         existing_mallocation->freed = false; | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |     m_mallocations.append({ address, size }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void MallocTracer::target_did_free(Badge<SoftCPU>, FlatPtr address) | ||||||
|  | { | ||||||
|  |     for (auto& mallocation : m_mallocations) { | ||||||
|  |         if (mallocation.address == address) { | ||||||
|  |             mallocation.freed = true; | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     ASSERT_NOT_REACHED(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | MallocTracer::Mallocation* MallocTracer::find_mallocation(FlatPtr address) | ||||||
|  | { | ||||||
|  |     for (auto& mallocation : m_mallocations) { | ||||||
|  |         if (mallocation.contains(address)) | ||||||
|  |             return &mallocation; | ||||||
|  |     } | ||||||
|  |     return nullptr; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void MallocTracer::audit_read(FlatPtr address, size_t size) | ||||||
|  | { | ||||||
|  |     if (Emulator::the().is_in_malloc_or_free()) | ||||||
|  |         return; | ||||||
|  | 
 | ||||||
|  |     auto* mallocation = find_mallocation(address); | ||||||
|  |     if (!mallocation) | ||||||
|  |         return; | ||||||
|  | 
 | ||||||
|  |     size_t offset_into_mallocation = address - mallocation->address; | ||||||
|  | 
 | ||||||
|  |     if (mallocation->freed) { | ||||||
|  |         dbgprintf("\n"); | ||||||
|  |         dbgprintf("==%d==  \033[31;1mUAF\033[0m, invalid %zu-byte read at address %p\n", s_pid, size, address); | ||||||
|  |         dbgprintf("==%d==  Address is %zu bytes into freed block of size %zu\n", s_pid, offset_into_mallocation, mallocation->size); | ||||||
|  |         Emulator::the().dump_backtrace(); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void MallocTracer::audit_write(FlatPtr address, size_t size) | ||||||
|  | { | ||||||
|  |     if (Emulator::the().is_in_malloc_or_free()) | ||||||
|  |         return; | ||||||
|  | 
 | ||||||
|  |     auto* mallocation = find_mallocation(address); | ||||||
|  |     if (!mallocation) | ||||||
|  |         return; | ||||||
|  | 
 | ||||||
|  |     size_t offset_into_mallocation = address - mallocation->address; | ||||||
|  | 
 | ||||||
|  |     if (mallocation->freed) { | ||||||
|  |         dbgprintf("\n"); | ||||||
|  |         dbgprintf("==%d==   \033[31;1mUAF\033[0m, invalid %zu-byte write at address %p\n", s_pid, size, address); | ||||||
|  |         dbgprintf("==%d==   Address is %zu bytes into freed block of size %zu\n", s_pid, offset_into_mallocation, mallocation->size); | ||||||
|  |         Emulator::the().dump_backtrace(); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | } | ||||||
							
								
								
									
										64
									
								
								DevTools/UserspaceEmulator/MallocTracer.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								DevTools/UserspaceEmulator/MallocTracer.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,64 @@ | ||||||
|  | /*
 | ||||||
|  |  * Copyright (c) 2020, Andreas Kling <kling@serenityos.org> | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions are met: | ||||||
|  |  * | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright notice, this | ||||||
|  |  *    list of conditions and the following disclaimer. | ||||||
|  |  * | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright notice, | ||||||
|  |  *    this list of conditions and the following disclaimer in the documentation | ||||||
|  |  *    and/or other materials provided with the distribution. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||||
|  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||||
|  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||||
|  |  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE | ||||||
|  |  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||||||
|  |  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | ||||||
|  |  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | ||||||
|  |  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | ||||||
|  |  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||||||
|  |  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <AK/Badge.h> | ||||||
|  | #include <AK/Types.h> | ||||||
|  | #include <AK/Vector.h> | ||||||
|  | 
 | ||||||
|  | namespace UserspaceEmulator { | ||||||
|  | 
 | ||||||
|  | class SoftCPU; | ||||||
|  | 
 | ||||||
|  | class MallocTracer { | ||||||
|  | public: | ||||||
|  |     MallocTracer(); | ||||||
|  | 
 | ||||||
|  |     void target_did_malloc(Badge<SoftCPU>, FlatPtr address, size_t); | ||||||
|  |     void target_did_free(Badge<SoftCPU>, FlatPtr address); | ||||||
|  | 
 | ||||||
|  |     void audit_read(FlatPtr address, size_t); | ||||||
|  |     void audit_write(FlatPtr address, size_t); | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |     struct Mallocation { | ||||||
|  |         bool contains(FlatPtr a) const | ||||||
|  |         { | ||||||
|  |             return a >= address && a < (address + size); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         FlatPtr address { 0 }; | ||||||
|  |         size_t size { 0 }; | ||||||
|  |         bool freed { false }; | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     Mallocation* find_mallocation(FlatPtr); | ||||||
|  | 
 | ||||||
|  |     Vector<Mallocation> m_mallocations; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | @ -61,6 +61,13 @@ MmapRegion::~MmapRegion() | ||||||
|         free(m_data); |         free(m_data); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | bool MmapRegion::is_malloc_block() const | ||||||
|  | { | ||||||
|  |     // FIXME: This is obviously incomplete!
 | ||||||
|  |     //        We should somehow know which mmap regions are malloc blocks.
 | ||||||
|  |     return !m_file_backed; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| u8 MmapRegion::read8(FlatPtr offset) | u8 MmapRegion::read8(FlatPtr offset) | ||||||
| { | { | ||||||
|     if (!is_readable()) { |     if (!is_readable()) { | ||||||
|  | @ -69,6 +76,11 @@ u8 MmapRegion::read8(FlatPtr offset) | ||||||
|         TODO(); |         TODO(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     if (is_malloc_block()) { | ||||||
|  |         if (auto* tracer = Emulator::the().malloc_tracer()) | ||||||
|  |             tracer->audit_read(base() + offset, 1); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     ASSERT(offset < size()); |     ASSERT(offset < size()); | ||||||
|     return *reinterpret_cast<const u8*>(m_data + offset); |     return *reinterpret_cast<const u8*>(m_data + offset); | ||||||
| } | } | ||||||
|  | @ -81,6 +93,11 @@ u16 MmapRegion::read16(u32 offset) | ||||||
|         TODO(); |         TODO(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     if (is_malloc_block()) { | ||||||
|  |         if (auto* tracer = Emulator::the().malloc_tracer()) | ||||||
|  |             tracer->audit_read(base() + offset, 2); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     ASSERT(offset + 1 < size()); |     ASSERT(offset + 1 < size()); | ||||||
|     return *reinterpret_cast<const u16*>(m_data + offset); |     return *reinterpret_cast<const u16*>(m_data + offset); | ||||||
| } | } | ||||||
|  | @ -93,6 +110,11 @@ u32 MmapRegion::read32(u32 offset) | ||||||
|         TODO(); |         TODO(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     if (is_malloc_block()) { | ||||||
|  |         if (auto* tracer = Emulator::the().malloc_tracer()) | ||||||
|  |             tracer->audit_read(base() + offset, 4); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     ASSERT(offset + 3 < size()); |     ASSERT(offset + 3 < size()); | ||||||
|     return *reinterpret_cast<const u32*>(m_data + offset); |     return *reinterpret_cast<const u32*>(m_data + offset); | ||||||
| } | } | ||||||
|  | @ -105,6 +127,11 @@ void MmapRegion::write8(u32 offset, u8 value) | ||||||
|         TODO(); |         TODO(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     if (is_malloc_block()) { | ||||||
|  |         if (auto* tracer = Emulator::the().malloc_tracer()) | ||||||
|  |             tracer->audit_write(base() + offset, 1); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     ASSERT(offset < size()); |     ASSERT(offset < size()); | ||||||
|     *reinterpret_cast<u8*>(m_data + offset) = value; |     *reinterpret_cast<u8*>(m_data + offset) = value; | ||||||
| } | } | ||||||
|  | @ -117,6 +144,11 @@ void MmapRegion::write16(u32 offset, u16 value) | ||||||
|         TODO(); |         TODO(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     if (is_malloc_block()) { | ||||||
|  |         if (auto* tracer = Emulator::the().malloc_tracer()) | ||||||
|  |             tracer->audit_write(base() + offset, 2); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     ASSERT(offset + 1 < size()); |     ASSERT(offset + 1 < size()); | ||||||
|     *reinterpret_cast<u16*>(m_data + offset) = value; |     *reinterpret_cast<u16*>(m_data + offset) = value; | ||||||
| } | } | ||||||
|  | @ -129,6 +161,11 @@ void MmapRegion::write32(u32 offset, u32 value) | ||||||
|         TODO(); |         TODO(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     if (is_malloc_block()) { | ||||||
|  |         if (auto* tracer = Emulator::the().malloc_tracer()) | ||||||
|  |             tracer->audit_write(base() + offset, 4); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     ASSERT(offset + 3 < size()); |     ASSERT(offset + 3 < size()); | ||||||
|     *reinterpret_cast<u32*>(m_data + offset) = value; |     *reinterpret_cast<u32*>(m_data + offset) = value; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -51,6 +51,8 @@ public: | ||||||
|     bool is_writable() const { return m_prot & PROT_WRITE; } |     bool is_writable() const { return m_prot & PROT_WRITE; } | ||||||
|     bool is_executable() const { return m_prot & PROT_EXEC; } |     bool is_executable() const { return m_prot & PROT_EXEC; } | ||||||
| 
 | 
 | ||||||
|  |     bool is_malloc_block() const; | ||||||
|  | 
 | ||||||
| private: | private: | ||||||
|     MmapRegion(u32 base, u32 size, int prot); |     MmapRegion(u32 base, u32 size, int prot); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -65,6 +65,19 @@ void SoftCPU::dump() const | ||||||
|     printf("o=%u s=%u z=%u a=%u p=%u c=%u\n", of(), sf(), zf(), af(), pf(), cf()); |     printf("o=%u s=%u z=%u a=%u p=%u c=%u\n", of(), sf(), zf(), af(), pf(), cf()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void SoftCPU::did_receive_secret_data() | ||||||
|  | { | ||||||
|  |     if (m_secret_data[0] == 1) { | ||||||
|  |         if (auto* tracer = m_emulator.malloc_tracer()) | ||||||
|  |             tracer->target_did_malloc({}, m_secret_data[2], m_secret_data[1]); | ||||||
|  |     } else if (m_secret_data[0] == 2) { | ||||||
|  |         if (auto* tracer = m_emulator.malloc_tracer()) | ||||||
|  |             tracer->target_did_free({}, m_secret_data[1]); | ||||||
|  |     } else { | ||||||
|  |         ASSERT_NOT_REACHED(); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void SoftCPU::update_code_cache() | void SoftCPU::update_code_cache() | ||||||
| { | { | ||||||
|     auto* region = m_emulator.mmu().find_region({ cs(), eip() }); |     auto* region = m_emulator.mmu().find_region({ cs(), eip() }); | ||||||
|  | @ -604,7 +617,6 @@ ALWAYS_INLINE static T op_shrd(SoftCPU& cpu, T data, T extra_bits, u8 steps) | ||||||
|     return result; |     return result; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| template<typename T> | template<typename T> | ||||||
| ALWAYS_INLINE static T op_shld(SoftCPU& cpu, T data, T extra_bits, u8 steps) | ALWAYS_INLINE static T op_shld(SoftCPU& cpu, T data, T extra_bits, u8 steps) | ||||||
| { | { | ||||||
|  | @ -633,7 +645,6 @@ ALWAYS_INLINE static T op_shld(SoftCPU& cpu, T data, T extra_bits, u8 steps) | ||||||
|     return result; |     return result; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| template<bool update_dest, typename Op> | template<bool update_dest, typename Op> | ||||||
| ALWAYS_INLINE void SoftCPU::generic_AL_imm8(Op op, const X86::Instruction& insn) | ALWAYS_INLINE void SoftCPU::generic_AL_imm8(Op op, const X86::Instruction& insn) | ||||||
| { | { | ||||||
|  | @ -1477,6 +1488,18 @@ void SoftCPU::PUSH_reg16(const X86::Instruction&) { TODO(); } | ||||||
| void SoftCPU::PUSH_reg32(const X86::Instruction& insn) | void SoftCPU::PUSH_reg32(const X86::Instruction& insn) | ||||||
| { | { | ||||||
|     push32(gpr32(insn.reg32())); |     push32(gpr32(insn.reg32())); | ||||||
|  | 
 | ||||||
|  |     if (m_secret_handshake_state == 2) { | ||||||
|  |         m_secret_data[0] = gpr32(insn.reg32()); | ||||||
|  |         ++m_secret_handshake_state; | ||||||
|  |     } else if (m_secret_handshake_state == 3) { | ||||||
|  |         m_secret_data[1] = gpr32(insn.reg32()); | ||||||
|  |         ++m_secret_handshake_state; | ||||||
|  |     } else if (m_secret_handshake_state == 4) { | ||||||
|  |         m_secret_data[2] = gpr32(insn.reg32()); | ||||||
|  |         m_secret_handshake_state = 0; | ||||||
|  |         did_receive_secret_data(); | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void SoftCPU::RCL_RM16_1(const X86::Instruction&) { TODO(); } | void SoftCPU::RCL_RM16_1(const X86::Instruction&) { TODO(); } | ||||||
|  | @ -1534,7 +1557,16 @@ void SoftCPU::ROR_RM8_1(const X86::Instruction&) { TODO(); } | ||||||
| void SoftCPU::ROR_RM8_CL(const X86::Instruction&) { TODO(); } | void SoftCPU::ROR_RM8_CL(const X86::Instruction&) { TODO(); } | ||||||
| void SoftCPU::ROR_RM8_imm8(const X86::Instruction&) { TODO(); } | void SoftCPU::ROR_RM8_imm8(const X86::Instruction&) { TODO(); } | ||||||
| void SoftCPU::SAHF(const X86::Instruction&) { TODO(); } | void SoftCPU::SAHF(const X86::Instruction&) { TODO(); } | ||||||
| void SoftCPU::SALC(const X86::Instruction&) { TODO(); } | 
 | ||||||
|  | void SoftCPU::SALC(const X86::Instruction&) | ||||||
|  | { | ||||||
|  |     set_al(cf() ? 0x01 : 0x00); | ||||||
|  | 
 | ||||||
|  |     if (m_secret_handshake_state < 2) | ||||||
|  |         ++m_secret_handshake_state; | ||||||
|  |     else | ||||||
|  |         m_secret_handshake_state = 0; | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| template<typename T> | template<typename T> | ||||||
| static T op_sar(SoftCPU& cpu, T data, u8 steps) | static T op_sar(SoftCPU& cpu, T data, u8 steps) | ||||||
|  |  | ||||||
|  | @ -799,6 +799,8 @@ private: | ||||||
| 
 | 
 | ||||||
|     void update_code_cache(); |     void update_code_cache(); | ||||||
| 
 | 
 | ||||||
|  |     void did_receive_secret_data(); | ||||||
|  | 
 | ||||||
| private: | private: | ||||||
|     Emulator& m_emulator; |     Emulator& m_emulator; | ||||||
| 
 | 
 | ||||||
|  | @ -810,6 +812,9 @@ private: | ||||||
| 
 | 
 | ||||||
|     const u8* m_cached_code_ptr { nullptr }; |     const u8* m_cached_code_ptr { nullptr }; | ||||||
|     const u8* m_cached_code_end { nullptr }; |     const u8* m_cached_code_end { nullptr }; | ||||||
|  | 
 | ||||||
|  |     u32 m_secret_handshake_state { 0 }; | ||||||
|  |     u32 m_secret_data[3]; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| ALWAYS_INLINE u8 SoftCPU::read8() | ALWAYS_INLINE u8 SoftCPU::read8() | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Andreas Kling
						Andreas Kling