mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 11:08:11 +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
|
@ -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());
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
template<bool update_dest, typename Op>
|
||||
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)
|
||||
{
|
||||
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(); }
|
||||
|
@ -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_imm8(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>
|
||||
static T op_sar(SoftCPU& cpu, T data, u8 steps)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue