#include "providers.h" #include "nls.h" #include #include #include #include #include static void check(bool value,const char *message) { if (!value) throw std::runtime_error(message); } static std::vector read_file(const std::filesystem::path &path) { std::ifstream file(path,std::ios::binary | std::ios::ate); check(bool(file) && file.tellg()>0 && file.tellg()<1024*1024,"invalid startup fixture"); std::vector bytes(size_t(file.tellg()));file.seekg(0); check(bool(file.read(reinterpret_cast(bytes.data()),std::streamsize(bytes.size()))),"short startup fixture");return bytes; } static uint64_t number(std::span bytes,size_t offset,size_t length) { uint64_t result=0;for(size_t i=0;i(byte))*1099511628211ULL; check(number(data("startup_title_digest",8),0,8)==digest,"ANSI startup title lost its initial data"); } std::vector images;for(const auto &[name,module] : modules.all()) images.push_back(&module->loaded); raven::NativeProcess process(images,argv[1],std::chrono::seconds(5)); raven::NativeEnvironment environment(process,entry.loaded.base(),1,1); environment.prepare_parameters({u"client.exe",u"command"}); const auto proxy=modules.resolve({"kernel32.dll","GetStartupInfoW",0,false,0}); const auto &kernel=*modules.all().at("kernel32.dll"); process.add_api_trap(raven::api_trap_address(kernel,"kernel32.dll","GetStartupInfoW",uint32_t(proxy-kernel.loaded.base()))); const auto invoke=[&](const char *name,uint64_t output) { const uint64_t args[]={output};check(process.call(proxy,args,std::chrono::seconds(2)).stop==raven::NativeStop::api,"startup proxy did not stop"); check(environment.dispatch(name),"startup handler did not dispatch");return process.resume(std::chrono::seconds(2)); }; const auto page=process.map_memory(8192,PROT_READ | PROT_WRITE); process.protect_memory(page+4096,4096,PROT_NONE); process.write_memory(page,std::vector(4096,0x5a));environment.set_last_error(91); check(invoke("GetStartupInfoW",page+4096-80).stop==raven::NativeStop::returned && environment.last_error()==91, "wide startup accessed unused standard handles across the mapping boundary"); const auto prefix=process.read_memory(page+4096-80,80);check(prefix[4]==0x5a && prefix[68]==0x5a,"wide padding changed"); process.protect_memory(page,4096,PROT_READ); const uint64_t args[]={page};check(process.call(proxy,args,std::chrono::seconds(2)).stop==raven::NativeStop::api,"readonly startup did not stop"); bool faulted=false; try { environment.dispatch("GetStartupInfoW"); } catch(const raven::NativeResult &fault) { faulted=fault.stop==raven::NativeStop::exception && fault.value==0xc0000005U && fault.fault_address==page && fault.exception_information==std::vector{1,page}; } check(faulted && process.read_memory(page+4096-80,80)==prefix && environment.last_error()==91,"readonly startup did not preserve output or report its write fault"); process.return_api(0);process.resume(std::chrono::seconds(2)); process.unmap_memory(page); std::cout<<"Native startup A snapshot, W live fields, padding, binary pointer and buffer bounds passed\n"; } catch(const std::exception &error) { std::cerr<