Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
GaryOderNichts committed Jun 6, 2022
0 parents commit 3c0cdd6
Show file tree
Hide file tree
Showing 39 changed files with 6,395 additions and 0 deletions.
21 changes: 21 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
name: Build

on: [push, pull_request]

jobs:
build-binary:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
with:
submodules: recursive
- name: Build pico
run: |
docker build -t udpihbuilder .
docker run --rm -v ${PWD}:/project udpihbuilder make pico
- uses: actions/upload-artifact@v2
with:
name: udpih
path: |
arm_kernel/arm_kernel.bin.h
pico/build/udpih.uf2
15 changes: 15 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
.vscode/
build/

*.elf
*.bin
*.bin.h

*.ko
*.o
*.o.cmd
*.cmd
*.symvers
*.mod
*.mod.c
*.order
11 changes: 11 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
FROM devkitpro/devkitarm:20220531

ENV PATH=$DEVKITARM/bin:$PATH

RUN apt-get update && apt-get -y install --no-install-recommends build-essential cmake gcc-arm-none-eabi libnewlib-arm-none-eabi libstdc++-arm-none-eabi-newlib && rm -rf /var/lib/apt/lists/*

# clone pico-sdk
RUN git clone https://github.com/raspberrypi/pico-sdk
ENV PICO_SDK_PATH=/pico-sdk

WORKDIR /project
339 changes: 339 additions & 0 deletions LICENSE

Large diffs are not rendered by default.

29 changes: 29 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#-------------------------------------------------------------------------------
.SUFFIXES:
#-------------------------------------------------------------------------------

.PHONY: all clean linux pico arm_kernel arm_user

all: linux pico
@echo "\033[92mDone!\033[0m"

arm_user:
@$(MAKE) --no-print-directory -C $(CURDIR)/arm_user

arm_kernel: arm_user
@$(MAKE) --no-print-directory -C $(CURDIR)/arm_kernel

linux: arm_kernel
@echo "\033[92mBuilding $@...\033[0m"
@$(MAKE) --no-print-directory -C $(CURDIR)/linux

pico: arm_kernel
@echo "\033[92mBuilding $@...\033[0m"
@$(MAKE) --no-print-directory -C $(CURDIR)/pico

clean:
@echo "\033[92mCleaning $@...\033[0m"
@$(MAKE) --no-print-directory -C $(CURDIR)/arm_user clean
@$(MAKE) --no-print-directory -C $(CURDIR)/arm_kernel clean
@$(MAKE) --no-print-directory -C $(CURDIR)/linux clean
@$(MAKE) --no-print-directory -C $(CURDIR)/pico clean
72 changes: 72 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# USB Descriptor Parsing Is Hard (UDPIH)
Exploits the Wii U's USB Host Stack descriptor parsing. Pronounced like "mud pie" without the M.

[The write-up can be found here!](https://garyodernichts.blogspot.com/2022/06/exploiting-wii-us-usb-descriptor-parsing.html)

## Requirements
- A Wii U
- A Raspberry Pi Pico or Zero

*Note: Any other linux device capable of USB device emulation should work as well.
Prebuilt releases are only available for the Pico and Zero.
I will add more devices below which are confirmed to work.*

## Instructions
### Pico
- Download the latest `udpih.uf2` from the [releases page](https://github.com/GaryOderNichts/udpih/releases).
- Hold down the `BOOTSEL` button on the board and connect the Pico to your PC.
Your PC will detect the Pi as a storage device.
- Copy the `.uf2` file to the Pico. It will disconnect after a few seconds.

The Pico is now flashed and can be used for udpih. Continue with ["Booting the recovery_menu"](#booting-the-recoverymenu) below.

### Raspberry Pi Zero (Linux)
- Install the required dependencies:
```bash
sudo apt install build-essential raspberrypi-kernel-headers
```
- Clone the repo:
```bash
git clone https://github.com/GaryOderNichts/udpih.git
cd udpih
```
- Download the latest `arm_kernel.bin.h` from the [releases page](https://github.com/GaryOderNichts/udpih/releases) and copy it to the `arm_kernel` directory.
- Now build the kernel module:
```bash
cd linux
make
```
- You can now run `sudo insmod udpih.ko` to insert the kernel module into the kernel.

The Zero is now ready to be used for udpih.
Note that you'll need to insert the module again after rebooting the Zero. You will need 2 USB cables, one for powering the Zero and one which can be connected to the Wii U.
Continue with ["Booting the recovery_menu"](#booting-the-recoverymenu) below.
### Booting the recovery_menu
> :warning: Important notes for this to work:
> - Make sure **no** other USB Devices are attached to the console.
> - Only use USB ports on the front of the console, the back ports **will not** work.
> - If your console has standby mode enabled, pull the power plug and turn it on from a full coldboot state.
- Copy the latest release of the [recovery_menu](https://github.com/GaryOderNichts/recovery_menu/releases) to the root of your FAT32 formatted SD Card.
- Insert the SD Card into the console and power it on.
- As soon as you see the "Wii U" logo on the TV or Gamepad plug in your Zero/Pico.
This timing is important. If you're already in the menu, the exploit won't work..
- After a few seconds you should be in the recovery menu.
Check out the [recovery_menu README](https://github.com/GaryOderNichts/recovery_menu) for more information about this menu.
## Building
```bash
# build the docker container
docker build -t udpihbuilder .
# build the pico code
docker run -it --rm -v ${PWD}:/project udpihbuilder make pico
# to only build the arm kernel code
docker run -it --rm -v ${PWD}:/project udpihbuilder make arm_kernel
```
**Special thanks to Maschell, rw-r-r-0644, QuarkTheAwesome, vgmoose, exjam, dimok789, and everyone else who contributed to the Wii U scene!**
139 changes: 139 additions & 0 deletions arm_kernel/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------

ifeq ($(strip $(DEVKITPRO)),)
$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=<path to>/devkitpro")
endif

TOPDIR ?= $(CURDIR)

#---------------------------------------------------------------------------------
# iosu_rules
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITARM)),)
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>/devkitARM")
endif

include $(DEVKITARM)/base_rules
export OBJDUMP := $(PREFIX)objdump

MACHDEP = -DSTARBUCK -mbig-endian -mcpu=arm926ej-s -msoft-float -mfloat-abi=soft

%.elf:
@echo linking ... $(notdir $@)
$(SILENTCMD)$(LD) $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@
#---------------------------------------------------------------------------------

#---------------------------------------------------------------------------------
# TARGET is the name of the output
# SOURCES is a list of directories containing source code
# DATA is a list of directories containing data files
# INCLUDES is a list of directories containing header files
#---------------------------------------------------------------------------------
TARGET := $(notdir $(CURDIR))
BUILD := build
SOURCES := source
DATA := data
INCLUDES := source

#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
CFLAGS := -Wall -std=gnu11 -Os -flto $(MACHDEP) $(INCLUDE) -Wno-stringop-overflow

ASFLAGS := $(MACHDEP)

LDFLAGS := -nostartfiles -nodefaultlibs -mbig-endian -flto \
-Wl,-L $(TOPDIR) -Wl,-Map,$(notdir $*.map),-T $(TOPDIR)/link.ld

LIBS := -lgcc

#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level
# containing include and lib
#---------------------------------------------------------------------------------
LIBDIRS :=

#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------

export TARGETNAME := $(TARGET)

export OUTPUT := $(CURDIR)/$(TARGET)
export TOPDIR := $(CURDIR)

export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))

export DEPSDIR := $(CURDIR)/$(BUILD)

CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))

export LD := $(CC)

export OFILES_BIN := $(addsuffix .o,$(BINFILES))
export OFILES_SRC := $(SFILES:.s=.o) $(CFILES:.c=.o)
export OFILES := $(OFILES_BIN) $(OFILES_SRC)
export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES)))

export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD)

export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)

.PHONY: $(BUILD) clean all
#---------------------------------------------------------------------------------
all: $(BUILD)

$(BUILD):
@[ -d $@ ] || mkdir -p $@
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile

#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) $(TARGET).elf $(TARGET).bin $(TARGET).bin.h

#---------------------------------------------------------------------------------
else

DEPENDS := $(OFILES:.o=.d)

#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
all : $(OUTPUT).bin.h

$(OUTPUT).elf : $(OFILES)

$(OUTPUT).bin: $(OUTPUT).elf
@echo "built ... $(notdir $@)"
@$(OBJCOPY) -j .text -j .rodata -j .data -O binary $(OUTPUT).elf $@

$(OUTPUT).bin.h: $(OUTPUT).bin
@raw2c $<
@cp $(TARGETNAME).c $@

$(OFILES_SRC) : $(HFILES_BIN)

#-------------------------------------------------------------------------------
# you need a rule like this for each extension you use as binary data
#-------------------------------------------------------------------------------
%.bin.o %_bin.h : %.bin
#-------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)

-include $(DEPENDS)

#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------
30 changes: 30 additions & 0 deletions arm_kernel/imports.ld
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
PROVIDE(memcpy = 0x08131d04);
PROVIDE(memset = 0x08131da0);
PROVIDE(strncpy = 0x081329b8);
PROVIDE(vsnprintf = 0x0813293c);
PROVIDE(snprintf = 0x08132988);

PROVIDE(disable_interrupts = 0x0812e778);
PROVIDE(enable_interrupts = 0x0812e78c);

PROVIDE(invalidate_icache = 0x0812dcf0);
PROVIDE(invalidate_dcache = 0x08120164);
PROVIDE(flush_dcache = 0x081200f0);
PROVIDE(setClientCapabilities = 0x081260a8);
PROVIDE(_iosMapSharedUserExecution = 0x08124f88);

PROVIDE(IOS_HeapAlloc = 0x081234e4);
PROVIDE(IOS_HeapAllocAligned = 0x08123464);
PROVIDE(IOS_HeapFree = 0x08123830);

PROVIDE(IOS_Open = 0x0812940c);
PROVIDE(IOS_Close = 0x08129368);
PROVIDE(IOS_Ioctl = 0x081290e0);
PROVIDE(IOS_Ioctlv = 0x0812903c);

PROVIDE(IOS_VirtToPhys = 0x08124484);
PROVIDE(IOS_Shutdown = 0xffffdc48);
PROVIDE(IOS_Reset = 0x08129760);

PROVIDE(disableMMU = 0x0812ea6c);
PROVIDE(enableMMU = 0x0812ea5c);
28 changes: 28 additions & 0 deletions arm_kernel/link.ld
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
OUTPUT_ARCH(arm)

INCLUDE "imports.ld"

SECTIONS {
. = (0x08135000);

.text : {
crt0.o(.init)
*(.text*);
}
.rodata : {
*(.rodata*)
}
.data : {
*(.data*)
}
/* .bss : {
*(.bss*)
} */

/DISCARD/ : {
*(*);
}
}

/* make sure we don't write into the recovery_menu area */
ASSERT((SIZEOF(.text) + SIZEOF(.rodata) + SIZEOF(.data) /*+ SIZEOF(.bss)*/) < 0x1000, "arm_kernel is too big");
9 changes: 9 additions & 0 deletions arm_kernel/source/crt0.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.section ".init"
.arm
.align 4

.extern _main
.type _main, %function

_start:
b _main
Loading

0 comments on commit 3c0cdd6

Please sign in to comment.