Skip to content

Commit

Permalink
Implement the IPA dump functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
DoranekoSystems committed Oct 20, 2024
1 parent f675a18 commit 1ef2f93
Show file tree
Hide file tree
Showing 8 changed files with 429 additions and 4 deletions.
9 changes: 7 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ Next, select a process and press the 「Open Process」 button.
### Debugger
Only watchpoints are supported in the iOS environment.
Only watchpoints are supported in the iOS environment.
<img width="500" alt="img4" src="https://github.com/user-attachments/assets/957910ec-0506-4951-b68b-1476764a3ae1">
Expand All @@ -66,7 +66,6 @@ The feature allows viewing and downloading files on the device
<img width="500" alt="img4" src="https://github.com/user-attachments/assets/9873a16a-57f4-42a5-8244-2cdeaf1278a2">
## Android
### Run
Expand Down Expand Up @@ -103,6 +102,7 @@ To build the project using GitHub Actions, follow these steps:
4. Above the list of workflow runs, click on "Run workflow".
5. In the dialog box that appears:
- Select the branch you want to run the workflow on (usually "main").
- Enter a version tag for this build (e.g., "v1.0.0").
Expand All @@ -120,4 +120,9 @@ To build the project using GitHub Actions, follow these steps:
Note: Make sure you have the necessary permissions in your forked repository to run workflows and access artifacts.
## Manual build
For more information, please visit [Wiki](https://github.com/DoranekoSystems/memory-server/wiki/Build)
# Credits
[frida-ios-dump](https://github.com/AloneMonkey/frida-ios-dump)
1 change: 1 addition & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"axios": "^1.7.4",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.0",
"jszip": "^3.10.1",
"lucide-react": "^0.453.0",
"next": "^14.2.10",
"path-browserify": "^1.0.1",
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { Scanner } from "@/components/Scanner";
import { Bookmark } from "@/components/Bookmark";
import { MemoryView } from "@/components/MemoryView";
import { Debugger } from "@/components/Debugger";
import { Tools } from "@/components/Tools";
import { Information } from "@/components/Information";
import { FileView } from "@/components/FileExplorer";
import { Header } from "@/components/Header";
Expand All @@ -21,6 +22,7 @@ export default function Home() {
bookmark: Bookmark,
memoryview: MemoryView,
debugger: Debugger,
tools: Tools,
information: Information,
fileexplorer: FileView,
};
Expand Down
4 changes: 3 additions & 1 deletion frontend/src/components/Setting/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export function Setting() {
const targetOS = useStore((state) => state.targetOS);
const setTargetOS = useStore((state) => state.setTargetOS);
const setIpAddress = useStore((state) => state.setIpAddress);
const setOpenProcessId = useStore((state) => state.setOpenProcessId);
const memoryApi = useStore((state) => state.memoryApi);
const setMemoryApi = useStore((state) => state.setMemoryApi);

Expand Down Expand Up @@ -97,7 +98,8 @@ export function Setting() {

if (result.success) {
setOpenedProcess(selectedProcess);
await fetchApplicationInfo(selectedProcess.pid); // Fetch Application Info after process is opened
await fetchApplicationInfo(selectedProcess.pid);
setOpenProcessId(selectedProcess.pid);
return true;
}
};
Expand Down
99 changes: 99 additions & 0 deletions frontend/src/components/Tools/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import {
CardTitle,
CardDescription,
CardHeader,
CardContent,
CardFooter,
Card,
} from "@/components/common/Card";
import { Label } from "@/components/common/Label";
import { Input } from "@/components/common/Input";
import { Button } from "@/components/common/Button";
import { useState, useEffect, useRef } from "react";
import { useStore } from "@/lib/global-store";
import { MemoryApi } from "@/lib/api";
import { dumpApp } from "@/lib/tools/ipa_dump";

export function Tools() {
const ipAddress = useStore((state) => state.ipAddress);
const openProcessId = useStore((state) => state.openProcessId);
const [progress, setProgress] = useState(0);
const [resultMessage, setResultMessage] = useState("");
const progressRef = useRef({ setProgress: setProgress });
const targetOS = useStore((state) => state.targetOS);

useEffect(() => {
progressRef.current.setProgress = setProgress;
}, [progressRef.current.setProgress]);

const ipaDump = async () => {
setProgress(0);
setResultMessage("");
try {
const result = await dumpApp(ipAddress, openProcessId, progressRef);
if (result.success) {
const url = window.URL.createObjectURL(result.ipaBlob);
const link = document.createElement("a");
link.href = url;
let ipaFileName = result.appName.replace(/\.app$/, ".ipa");
link.setAttribute("download", ipaFileName);
document.body.appendChild(link);
link.click();
link.parentNode.removeChild(link);
setResultMessage("IPA dump completed successfully!");
} else {
setResultMessage("Failed to dump IPA. Please try again.");
}
} catch (error) {
setResultMessage(`Error occurred: ${error.message}`);
}
};

return (
<div className="flex flex-col min-h-screen">
<main className="flex flex-col items-center flex-grow px-4 mt-8">
{targetOS === "ios" ? (
<Card className="w-full max-w-md mb-6">
<CardHeader>
<CardTitle className="text-2xl">IPA Dump</CardTitle>
<CardDescription>
Dump the IPA after decrypting the binary from memory.
</CardDescription>
</CardHeader>
<CardContent>
{progress > 0 && (
<div className="w-full bg-gray-200 rounded-full h-2.5 mb-4 dark:bg-gray-700">
<div
className="bg-blue-600 h-2.5 rounded-full"
style={{ width: `${progress}%` }}
></div>
</div>
)}
{resultMessage && (
<div
className={`mt-4 p-2 rounded ${
resultMessage.includes("Failed") ||
resultMessage.includes("Error")
? "bg-red-100 text-red-700"
: "bg-green-100 text-green-700"
}`}
>
{resultMessage}
</div>
)}
</CardContent>
<CardFooter>
<Button
className="w-full"
onClick={ipaDump}
disabled={progress > 0 && progress < 100}
>
Dump
</Button>
</CardFooter>
</Card>
) : null}
</main>
</div>
);
}
6 changes: 6 additions & 0 deletions frontend/src/components/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@ export function Header({ changePage }): any {
) : (
""
)}
<button
className="text-sm font-medium hover:underline underline-offset-4"
onClick={() => changePage("tools")}
>
Tools
</button>
<button
className="text-sm font-medium hover:underline underline-offset-4"
onClick={() => changePage("information")}
Expand Down
Loading

0 comments on commit 1ef2f93

Please sign in to comment.