Merge remote-tracking branch 'origin/main' into unicorn-upgrade-2

This commit is contained in:
Maurice Heumann
2025-08-24 08:43:38 +02:00
14 changed files with 69 additions and 1575 deletions

View File

@@ -18,12 +18,6 @@ updates:
interval: monthly
open-pull-requests-limit: 100
- package-ecosystem: "npm"
directory: "/mcp"
schedule:
interval: monthly
open-pull-requests-limit: 100
- package-ecosystem: "cargo"
directory: "/src/backends/icicle-emulator/icicle-bridge/"
schedule:

View File

@@ -144,6 +144,10 @@ if(CMAKE_SYSTEM_NAME MATCHES "Emscripten")
endif()
if(MOMO_EMSCRIPTEN_SUPPORT_NODEJS)
add_compile_definitions(
MOMO_EMSCRIPTEN_SUPPORT_NODEJS=1
)
add_link_options(
-lnodefs.js -sNODERAWFS=1
-sENVIRONMENT=node

41
mcp/.gitignore vendored
View File

@@ -1,41 +0,0 @@
# Dependencies
node_modules/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Coverage directory used by tools like istanbul
coverage/
*.lcov
# nyc test coverage
.nyc_output
# Environment variables
.env
.env.local
.env.development.local
.env.test.local
.env.production.local
# Editor directories and files
.vscode/
.idea/
*.swp
*.swo
*~
# OS generated files
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db

View File

@@ -1,118 +0,0 @@
# Sogen MCP Server
A Model Context Protocol (MCP) server that provides AI access to the sogen userspace emulator.
## Setup
1. Install dependencies:
```bash
npm install
```
2. Run the server:
```bash
npm start
```
Or for development with auto-restart:
```bash
npm run dev
```
## Structure
- `server.js` - Main server implementation
- `package.json` - Node.js project configuration
## Available Tools
### `list_applications`
Lists all available applications in the sogen userspace emulator.
**Parameters:** None
**Example usage:**
```json
{
"name": "list_applications",
"arguments": {}
}
```
### `run_application`
Executes a specific application from the allowed list in the sogen userspace emulator.
**Parameters:**
- `application` (string, required): The name of the application to run (use `list_applications` to see available apps)
- `args` (array of strings, optional): Arguments to pass to the application
- `timeout` (number, optional): Timeout in milliseconds (default: 5000)
**Example usage:**
```json
{
"name": "run_application",
"arguments": {
"application": "echo",
"args": ["Hello from sogen!"],
"timeout": 3000
}
}
```
## Adding More Tools
To add additional tools:
1. Add the tool definition to the `ListToolsRequestSchema` handler
2. Add the implementation to the `CallToolRequestSchema` handler
3. Create the corresponding method in the `MyMCPServer` class
## Execution Model
The server uses an **analyzer-based execution model**:
- Applications are not executed directly
- Instead, the server runs: `C:/analyer.exe -e C:/somedir <application_name> [args...]`
- The analyzer handles the actual execution within the sogen environment
- All output comes from the analyzer process
### Command Structure
```
C:/analyer.exe -e C:/somedir <application_name> [arguments...]
```
Where:
- `C:/analyer.exe` - The sogen analyzer executable
- `-e C:/somedir` - Analyzer flags and environment directory
- `<application_name>` - The application from `get_applications()`
- `[arguments...]` - Optional arguments passed to the application
## Implementation Required
You need to provide the implementation for the `get_applications()` method in `server.js`. This method should:
```javascript
async get_applications() {
// Return a Promise that resolves to a string array
// Example: return ['echo', 'ls', 'cat', 'grep'];
}
```
## Usage
This server allows AI assistants to:
1. **List available applications** using `list_applications`
2. **Execute specific applications** using `run_application` with validation
The server communicates over stdio and is designed for MCP-compatible clients.
### Example Workflow
1. Call `list_applications` to see what's available
2. Call `run_application` with a valid application name and arguments
## Next Steps
1. **Implement `get_applications()` method** - Provide the actual implementation
2. Add application-specific argument validation
3. Implement resource handling for file access
4. Add comprehensive logging and monitoring
5. Consider per-application sandboxing for enhanced security

1041
mcp/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,17 +0,0 @@
{
"name": "sogen-mcp-server",
"version": "1.0.0",
"description": "MCP server for sogen userspace emulator",
"main": "server.js",
"type": "module",
"scripts": {
"start": "node server.js",
"dev": "node --watch server.js"
},
"dependencies": {
"@modelcontextprotocol/sdk": "^1.17.3"
},
"keywords": ["mcp", "server"],
"author": "",
"license": "MIT"
}

View File

@@ -1,296 +0,0 @@
#!/usr/bin/env node
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
CallToolRequestSchema,
ListToolsRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";
import { spawn } from "child_process";
import path from "path";
import { fileURLToPath } from "url";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
class SogenMCPServer {
constructor() {
this.server = new Server(
{
name: "sogen-mcp-server",
version: "1.0.0",
},
{
capabilities: {
tools: {},
},
}
);
this.setupToolHandlers();
this.setupErrorHandling();
}
setupToolHandlers() {
// Handle tool listing
this.server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: [
{
name: "list_applications",
description:
"List all available applications in the sogen userspace emulator",
inputSchema: {
type: "object",
properties: {},
additionalProperties: false,
},
},
{
name: "run_application",
description:
"Execute a specific application in the sogen userspace emulator",
inputSchema: {
type: "object",
properties: {
application: {
type: "string",
description:
"The name of the application to run (use list_applications to see available apps)",
},
args: {
type: "array",
items: {
type: "string",
},
description: "Arguments to pass to the application",
default: [],
},
timeout: {
type: "number",
description: "Timeout in milliseconds (default: 50000)",
default: 50000,
},
},
required: ["application"],
},
},
],
};
});
// Handle tool execution
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
switch (name) {
case "list_applications":
return await this.listApplications();
case "run_application":
return await this.runApplication(
args.application,
args.args || [],
args.timeout || 50000
);
default:
throw new Error(`Unknown tool: ${name}`);
}
});
}
async listApplications() {
try {
const applications = await this.get_applications();
return {
content: [
{
type: "text",
text: `Available applications in sogen:\n\n${applications
.map((app) => `${app}`)
.join("\n")}\n\nTotal: ${applications.length} application(s)`,
},
],
};
} catch (error) {
return {
content: [
{
type: "text",
text: `Error listing applications: ${error.message}`,
},
],
};
}
}
async runApplication(applicationName, args = [], timeout = 5000) {
try {
// First, get the list of available applications to validate
const availableApps = await this.get_applications();
if (!availableApps.includes(applicationName)) {
return {
content: [
{
type: "text",
text: `Error: Application '${applicationName}' is not available.\n\nAvailable applications:\n${availableApps
.map((app) => `${app}`)
.join("\n")}`,
},
],
};
}
return await this.executeApplication(applicationName, args, timeout);
} catch (error) {
return {
content: [
{
type: "text",
text: `Error running application '${applicationName}': ${error.message}`,
},
],
};
}
}
async executeApplication(applicationName, args, timeout) {
return new Promise((resolve, reject) => {
// Get the parent directory (emulator root)
const emulatorRoot = path.dirname(__dirname);
// Build the analyzer command: C:/analyer.exe -e C:/somedir <application_name>
const analyzerPath =
"C:\\Users\\mauri\\Desktop\\emulator\\build\\vs2022\\artifacts-relwithdebinfo\\analyzer.exe";
const analyzerArgs = [
"-c",
"-e",
"C:\\Users\\mauri\\Desktop\\emulator\\src\\tools\\root",
applicationName,
...args,
];
const child = spawn(analyzerPath, analyzerArgs, {
cwd: "C:\\Users\\mauri\\Desktop\\emulator\\build\\vs2022\\artifacts-relwithdebinfo",
shell: true,
stdio: ["pipe", "pipe", "pipe"],
});
let stdout = "";
let stderr = "";
let timedOut = false;
// Set up timeout
const timer = setTimeout(() => {
timedOut = true;
child.kill("SIGTERM");
}, timeout);
// Collect stdout
child.stdout.on("data", (data) => {
stdout += data.toString();
});
// Collect stderr
child.stderr.on("data", (data) => {
stderr += data.toString();
});
// Handle process completion
child.on("close", (code) => {
clearTimeout(timer);
if (timedOut) {
resolve({
content: [
{
type: "text",
text: `Application '${applicationName}' timed out after ${timeout}ms\nAnalyzer command: ${analyzerPath} ${analyzerArgs.join(
" "
)}\nPartial stdout: ${stdout}\nPartial stderr: ${stderr}`,
},
],
});
} else {
const output = [];
if (stdout) {
output.push(`STDOUT:\n${stdout}`);
}
if (stderr) {
output.push(`STDERR:\n${stderr}`);
}
if (!stdout && !stderr) {
output.push("Application executed successfully with no output.");
}
output.push(`Exit code: ${code}`);
resolve({
content: [
{
type: "text",
text: `Application: ${applicationName}\nArguments: [${args.join(
", "
)}]\nAnalyzer command: ${analyzerPath} ${analyzerArgs.join(
" "
)}\n\n${output.join("\n\n")}`,
},
],
});
}
});
// Handle spawn errors
child.on("error", (error) => {
clearTimeout(timer);
resolve({
content: [
{
type: "text",
text: `Error executing application '${applicationName}' via analyzer: ${
error.message
}\nAnalyzer command: ${analyzerPath} ${analyzerArgs.join(" ")}`,
},
],
});
});
});
}
async get_applications() {
return [
"c:/test-sample.exe",
"c:/wukong/b1/Binaries/Win64/b1-Win64-Shipping.exe",
];
}
setupErrorHandling() {
this.server.onerror = (error) => {
console.error("[MCP Error]", error);
};
process.on("SIGINT", async () => {
await this.server.close();
process.exit(0);
});
}
async run() {
const transport = new StdioServerTransport();
await this.server.connect(transport);
console.error("MCP Server running on stdio");
}
}
// Start the server
const server = new SogenMCPServer();
server.run().catch((error) => {
console.error("Failed to start server:", error);
process.exit(1);
});

View File

@@ -19,42 +19,34 @@
content="Sogen is a high-performance Windows user space emulator that can emulate windows processes. It is ideal for security-, DRM- or malware research."
data-react-helmet="true"
/>
<meta
property="og:site_name"
content="Sogen - Windows User Space Emulator"
data-react-helmet="true"
/>
<meta
property="og:title"
content="Sogen - Windows User Space Emulator"
data-react-helmet="true"
/>
<meta property="og:site_name" content="Sogen" data-react-helmet="true" />
<meta property="og:title" content="Sogen" data-react-helmet="true" />
<meta
property="og:description"
content="Sogen is a high-performance Windows user space emulator that can emulate windows processes. It is ideal for security-, DRM- or malware research."
content="A high-performance Windows user space emulator."
data-react-helmet="true"
/>
<meta property="og:locale" content="en-us" data-react-helmet="true" />
<meta property="og:type" content="website" data-react-helmet="true" />
<meta
name="og:image"
content="https://repository-images.githubusercontent.com/842883987/9e56f43b-4afd-464d-85b9-d7e555751a39"
content="https://momo5502.com/emulator/preview.png"
data-react-helmet="true"
/>
<meta name="twitter:card" content="summary" data-react-helmet="true" />
<meta
name="twitter:title"
content="Sogen - Windows User Space Emulator"
name="twitter:card"
content="summary_large_image"
data-react-helmet="true"
/>
<meta name="twitter:title" content="Sogen" data-react-helmet="true" />
<meta
name="twitter:description"
content="Sogen is a high-performance Windows user space emulator that can emulate windows processes. It is ideal for security-, DRM- or malware research."
content="A high-performance Windows user space emulator."
data-react-helmet="true"
/>
<meta
name="twitter:image"
content="https://repository-images.githubusercontent.com/842883987/9e56f43b-4afd-464d-85b9-d7e555751a39"
content="https://momo5502.com/emulator/preview.png"
data-react-helmet="true"
/>
</head>

View File

@@ -6,8 +6,7 @@ export interface HeaderProps {
preload?: string[];
}
const image =
"https://repository-images.githubusercontent.com/842883987/9e56f43b-4afd-464d-85b9-d7e555751a39";
const image = "https://momo5502.com/emulator/preview.png";
export function Header(props: HeaderProps) {
return (
@@ -20,7 +19,7 @@ export function Header(props: HeaderProps) {
<meta property="og:locale" content="en-us" />
<meta property="og:type" content="website" />
<meta name="og:image" content={image} />
<meta name="twitter:card" content="summary" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content={props.title} />
<meta name="twitter:description" content={props.description} />
<meta name="twitter:image" content={image} />

View File

@@ -30,7 +30,7 @@ export function LandingPage() {
icon: <Split className="h-8 w-8" />,
title: "Hooking Capabilities",
description:
"Provides flexible hooking interfaces to intercept memory access, code execution and much more",
"Provides powerful hooking interfaces to intercept memory access, code execution and much more",
accent: "from-[#ffcb00] to-[#da6000]",
},
{
@@ -80,14 +80,14 @@ export function LandingPage() {
return (
<>
<Header
title="Sogen - Windows User Space Emulator"
description="Sogen is a high-performance Windows user space emulator that can emulate windows processes. It is ideal for security-, DRM- or malware research."
title="Sogen"
description="A high-performance Windows user space emulator."
/>
<div className="flex flex-col min-h-screen bg-gradient-to-br from-zinc-900 via-neutral-900 to-black">
{/* Hero Section with Animated Background */}
<section className="relative overflow-hidden">
<section className="relative overflow-visible">
{/* Animated Background Elements */}
<div className="absolute inset-0">
<div className="absolute inset-0 container mx-auto ">
<div className="absolute top-20 left-10 w-72 h-72 bg-yellow-500/10 rounded-full blur-3xl"></div>
<div className="absolute top-40 right-20 w-96 h-96 bg-lime-500/10 rounded-full blur-3xl"></div>
<div className="absolute bottom-20 left-1/3 w-80 h-80 bg-cyan-500/10 rounded-full blur-3xl"></div>
@@ -108,23 +108,29 @@ export function LandingPage() {
<div className="flex flex-col sm:flex-row gap-4 justify-center items-center pt-8">
<a href="#/playground">
<Button
asChild
size="lg"
className="bg-gradient-to-br from-white to-neutral-300 text-neutral-900 border-0 px-8 py-6 text-lg font-semibold group transition-all duration-100 transform hover:scale-105"
className="bg-gradient-to-br from-white to-neutral-300 text-neutral-900 border-0 px-8 py-6 text-lg font-semibold group transition-all duration-100"
>
<Play className="mr-2 h-5 w-5 group-hover:scale-110 transition-transform" />
Try Online
<ArrowRight className="ml-2 h-5 w-5 group-hover:translate-x-1 transition-transform" />
<span>
<Play className="mr-2 h-5 w-5 transition-transform" />
Try Online
<ArrowRight className="ml-2 h-5 w-5 group-hover:translate-x-1 transition-transform" />
</span>
</Button>
</a>
<a href="https://github.com/momo5502/sogen" target="_blank">
<Button
asChild
size="lg"
variant="outline"
className="border-neutral-600 text-neutral-300 hover:bg-neutral-800/50 px-8 py-6 text-lg font-semibold group transition-all duration-300"
>
<Github className="mr-2 h-5 w-5 group-hover:scale-110 transition-transform" />
View Source
<ExternalLink className="ml-2 h-4 w-4" />
<span>
<Github className="mr-2 h-5 w-5 group-hover:scale-110 transition-transform" />
View Source
<ExternalLink className="ml-2 h-4 w-4" />
</span>
</Button>
</a>
</div>
@@ -164,7 +170,7 @@ export function LandingPage() {
>
<CardHeader className="pb-4">
<div
className={`w-16 h-16 rounded-xl bg-gradient-to-br ${feature.accent} p-4 mb-4 transition-transform duration-200`}
className={`w-16 h-16 rounded-xl bg-gradient-to-br ${feature.accent} p-4 mb-4`}
>
<div className="text-neutral-900">{feature.icon}</div>
</div>
@@ -200,9 +206,9 @@ export function LandingPage() {
{useCases.map((useCase, index) => (
<div
key={index}
className="text-center p-8 rounded-2xl bg-neutral-800/50 border border-neutral-700 hover:border-blue-400/50 transition-all duration-300 group"
className="text-center p-8 rounded-2xl bg-neutral-800/50 border border-neutral-700 hover:border-blue-400/50 transition-all duration-200 group"
>
<div className="w-12 h-12 mx-auto mb-4 rounded-xl bg-gradient-to-br from-cyan-500 to-blue-500 p-3 group-hover:scale-110 transition-transform">
<div className="w-12 h-12 mx-auto mb-4 rounded-xl bg-gradient-to-br from-cyan-500 to-blue-500 p-3">
<div className="text-neutral-800">{useCase.icon}</div>
</div>
<h3 className="text-xl font-semibold text-white mb-3">
@@ -231,16 +237,19 @@ export function LandingPage() {
<div className="max-w-3xl mx-auto">
<div className="relative group">
<div className="absolute -inset-4 bg-gradient-to-r from-neutral-500/10 to-neutral-500/10 rounded-3xl blur-xl group-hover:blur-2xl transition-all duration-300"></div>
<div className="relative aspect-video rounded-2xl overflow-hidden border border-neutral-700">
<iframe
className="w-full h-full"
src="https://www.youtube.com/embed/wY9Q0DhodOQ?si=Lm_anpeBU6Txl5AW"
title="Sogen Emulator Overview"
frameBorder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
referrerPolicy="strict-origin-when-cross-origin"
allowFullScreen
></iframe>
<div className="relative aspect-video rounded-2xl overflow-hidden ">
{["wY9Q0DhodOQ"].map((value, index) => (
<iframe
key={index}
className="w-full h-full"
title="Sogen Emulator Overview"
frameBorder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
referrerPolicy="strict-origin-when-cross-origin"
allowFullScreen
srcDoc={`<style>*{padding:0;margin:0;overflow:hidden}html,body{height:100%}img,div{position:absolute;width:100%;top:0;bottom:0;margin:auto;}div{height:1.5em;text-align:center;font:30px/1.5 sans-serif;color:white;overflow:visible;}span{background:red;padding:10px 20px;border-radius:15px;box-shadow: 3px 5px 10px #0000007a;}</style><a href=https://www.youtube.com/embed/${value}/?autoplay=1><img src=https://img.youtube.com/vi/${value}/maxresdefault.jpg><div><span>&nbsp;▶</span></div></a>`}
></iframe>
))}
</div>
</div>
</div>
@@ -248,7 +257,7 @@ export function LandingPage() {
</section>
{/* CTA Section */}
<section className="py-24 bg-gradient-to-r from-neutral-900 to-zinc-900">
<section className="py-24 bg-gradient-to-r from-neutral-800/40 to-neutral-900">
<div className="container mx-auto px-6 text-center">
<h2 className="text-4xl font-bold text-white mb-6">
Ready to Start Emulating?
@@ -259,21 +268,27 @@ export function LandingPage() {
<div className="flex flex-col sm:flex-row gap-4 justify-center">
<a href="#/playground">
<Button
asChild
size="lg"
className="bg-gradient-to-br from-white to-neutral-300 text-neutral-900 px-8 py-6 text-lg font-semibold transition-all duration-100"
>
<Play className="mr-2 h-5 w-5" />
Launch Playground
<span>
<Play className="mr-2 h-5 w-5" />
Launch Playground
</span>
</Button>
</a>
<a href="https://github.com/momo5502/sogen" target="_blank">
<Button
asChild
size="lg"
variant="outline"
className="border-white text-white hover:bg-white/10 px-8 py-6 text-lg font-semibold"
>
<Download className="mr-2 h-5 w-5" />
Get Source
<span>
<Download className="mr-2 h-5 w-5" />
Get Source
</span>
</Button>
</a>
</div>
@@ -310,12 +325,14 @@ export function LandingPage() {
<a
href="https://github.com/momo5502/sogen"
target="_blank"
title="Soure Code"
className="text-neutral-400 hover:text-blue-400 transition-colors p-2 rounded-lg hover:bg-neutral-800/50"
>
<Github className="h-6 w-6" />
</a>
<a
href="#/playground"
title="Playground"
className="text-neutral-400 hover:text-blue-400 transition-colors p-2 rounded-lg hover:bg-neutral-800/50"
>
<Play className="h-6 w-6" />
@@ -323,6 +340,7 @@ export function LandingPage() {
<a
href="https://github.com/momo5502/sogen/wiki"
target="_blank"
title="Wiki"
className="text-neutral-400 hover:text-blue-400 transition-colors p-2 rounded-lg hover:bg-neutral-800/50"
>
<BookOpen className="h-6 w-6" />

View File

@@ -293,7 +293,7 @@ export class Playground extends React.Component<
<>
<Header
title="Sogen - Playground"
description="Playground to test and run Sogen, the Windows user space emulator, right in your browser."
description="Playground to test and run Sogen, a Windows user space emulator, right in your browser."
preload={
[
/*"./emulator-worker.js", "./analyzer.js", "./analyzer.wasm"*/

View File

@@ -5,7 +5,7 @@
#include "windows_emulator.hpp"
#include <utils/lazy_object.hpp>
#ifdef OS_EMSCRIPTEN
#if defined(OS_EMSCRIPTEN) && !defined(MOMO_EMSCRIPTEN_SUPPORT_NODEJS)
#include <event_handler.hpp>
#endif
@@ -299,7 +299,7 @@ namespace
auto& win_emu = *c.win_emu;
update_import_access(c, address);
#ifdef OS_EMSCRIPTEN
#if defined(OS_EMSCRIPTEN) && !defined(MOMO_EMSCRIPTEN_SUPPORT_NODEJS)
if ((win_emu.get_executed_instructions() % 0x20000) == 0)
{
debugger::event_context ec{.win_emu = win_emu};

View File

@@ -14,7 +14,7 @@
#include <utils/finally.hpp>
#include <utils/interupt_handler.hpp>
#ifdef OS_EMSCRIPTEN
#if defined(OS_EMSCRIPTEN) && !defined(MOMO_EMSCRIPTEN_SUPPORT_NODEJS)
#include <event_handler.hpp>
#endif
@@ -275,7 +275,7 @@ namespace
}};
std::optional<NTSTATUS> exit_status{};
#ifdef OS_EMSCRIPTEN
#if defined(OS_EMSCRIPTEN) && !defined(MOMO_EMSCRIPTEN_SUPPORT_NODEJS)
const auto _1 = utils::finally([&] {
debugger::handle_exit(win_emu, exit_status); //
});

View File

@@ -8,7 +8,7 @@ namespace
#ifdef _WIN32
#define COLOR(win, posix, web) win
using color_type = WORD;
#elif defined(__EMSCRIPTEN__)
#elif defined(__EMSCRIPTEN__) && !defined(MOMO_EMSCRIPTEN_SUPPORT_NODEJS)
#define COLOR(win, posix, web) web
using color_type = const char*;
#else