diff --git a/src/core/hle/service/nwm/nwm.cpp b/src/core/hle/service/nwm/nwm.cpp
index 8d63cb89f..a9b198281 100644
--- a/src/core/hle/service/nwm/nwm.cpp
+++ b/src/core/hle/service/nwm/nwm.cpp
@@ -2,7 +2,6 @@
 // Licensed under GPLv2 or any later version
 // Refer to the license.txt file included.
 
-#include <cryptopp/osrng.h>
 #include "core/hle/service/nwm/nwm.h"
 #include "core/hle/service/nwm/nwm_cec.h"
 #include "core/hle/service/nwm/nwm_ext.h"
@@ -11,35 +10,17 @@
 #include "core/hle/service/nwm/nwm_soc.h"
 #include "core/hle/service/nwm/nwm_tst.h"
 #include "core/hle/service/nwm/nwm_uds.h"
-#include "core/hle/shared_page.h"
-#include "network/network.h"
 
 namespace Service {
 namespace NWM {
 
-void Init() {
-    AddService(new NWM_CEC);
-    AddService(new NWM_EXT);
-    AddService(new NWM_INF);
-    AddService(new NWM_SAP);
-    AddService(new NWM_SOC);
-    AddService(new NWM_TST);
-
-    CryptoPP::AutoSeededRandomPool rng;
-    auto mac = SharedPage::DefaultMac;
-    // Keep the Nintendo 3DS MAC header and randomly generate the last 3 bytes
-    rng.GenerateBlock(static_cast<CryptoPP::byte*>(mac.data() + 3), 3);
-
-    if (auto room_member = Network::GetRoomMember().lock()) {
-        if (room_member->IsConnected()) {
-            mac = room_member->GetMacAddress();
-        }
-    }
-    SharedPage::SetMacAddress(mac);
-    SharedPage::SetWifiLinkLevel(SharedPage::WifiLinkLevel::BEST);
-}
-
 void InstallInterfaces(SM::ServiceManager& service_manager) {
+    std::make_shared<NWM_CEC>()->InstallAsService(service_manager);
+    std::make_shared<NWM_EXT>()->InstallAsService(service_manager);
+    std::make_shared<NWM_INF>()->InstallAsService(service_manager);
+    std::make_shared<NWM_SAP>()->InstallAsService(service_manager);
+    std::make_shared<NWM_SOC>()->InstallAsService(service_manager);
+    std::make_shared<NWM_TST>()->InstallAsService(service_manager);
     std::make_shared<NWM_UDS>()->InstallAsService(service_manager);
 }
 
diff --git a/src/core/hle/service/nwm/nwm.h b/src/core/hle/service/nwm/nwm.h
index 9c560c3ab..a5e9ba205 100644
--- a/src/core/hle/service/nwm/nwm.h
+++ b/src/core/hle/service/nwm/nwm.h
@@ -10,7 +10,6 @@ namespace Service {
 namespace NWM {
 
 /// Initialize all NWM services
-void Init();
 void InstallInterfaces(SM::ServiceManager& service_manager);
 
 } // namespace NWM
diff --git a/src/core/hle/service/nwm/nwm_cec.cpp b/src/core/hle/service/nwm/nwm_cec.cpp
index 7f03987df..df778f667 100644
--- a/src/core/hle/service/nwm/nwm_cec.cpp
+++ b/src/core/hle/service/nwm/nwm_cec.cpp
@@ -7,12 +7,11 @@
 namespace Service {
 namespace NWM {
 
-const Interface::FunctionInfo FunctionTable[] = {
-    {0x000D0082, nullptr, "SendProbeRequest"},
-};
-
-NWM_CEC::NWM_CEC() {
-    Register(FunctionTable);
+NWM_CEC::NWM_CEC() : ServiceFramework("nwm::CEC") {
+    static const FunctionInfo functions[] = {
+        {0x000D0082, nullptr, "SendProbeRequest"},
+    };
+    RegisterHandlers(functions);
 }
 
 } // namespace NWM
diff --git a/src/core/hle/service/nwm/nwm_cec.h b/src/core/hle/service/nwm/nwm_cec.h
index 07b6addb5..db1825b1f 100644
--- a/src/core/hle/service/nwm/nwm_cec.h
+++ b/src/core/hle/service/nwm/nwm_cec.h
@@ -9,13 +9,9 @@
 namespace Service {
 namespace NWM {
 
-class NWM_CEC final : public Interface {
+class NWM_CEC final : public ServiceFramework<NWM_CEC> {
 public:
     NWM_CEC();
-
-    std::string GetPortName() const override {
-        return "nwm::CEC";
-    }
 };
 
 } // namespace NWM
diff --git a/src/core/hle/service/nwm/nwm_ext.cpp b/src/core/hle/service/nwm/nwm_ext.cpp
index 605640a13..fd3903a22 100644
--- a/src/core/hle/service/nwm/nwm_ext.cpp
+++ b/src/core/hle/service/nwm/nwm_ext.cpp
@@ -7,12 +7,11 @@
 namespace Service {
 namespace NWM {
 
-const Interface::FunctionInfo FunctionTable[] = {
-    {0x00080040, nullptr, "ControlWirelessEnabled"},
-};
-
-NWM_EXT::NWM_EXT() {
-    Register(FunctionTable);
+NWM_EXT::NWM_EXT() : ServiceFramework("nwm::EXT") {
+    static const FunctionInfo functions[] = {
+        {0x00080040, nullptr, "ControlWirelessEnabled"},
+    };
+    RegisterHandlers(functions);
 }
 
 } // namespace NWM
diff --git a/src/core/hle/service/nwm/nwm_ext.h b/src/core/hle/service/nwm/nwm_ext.h
index 51d39d9ea..ed15d18a2 100644
--- a/src/core/hle/service/nwm/nwm_ext.h
+++ b/src/core/hle/service/nwm/nwm_ext.h
@@ -9,13 +9,9 @@
 namespace Service {
 namespace NWM {
 
-class NWM_EXT final : public Interface {
+class NWM_EXT final : public ServiceFramework<NWM_EXT> {
 public:
     NWM_EXT();
-
-    std::string GetPortName() const override {
-        return "nwm::EXT";
-    }
 };
 
 } // namespace NWM
diff --git a/src/core/hle/service/nwm/nwm_inf.cpp b/src/core/hle/service/nwm/nwm_inf.cpp
index c8470589b..6663e100c 100644
--- a/src/core/hle/service/nwm/nwm_inf.cpp
+++ b/src/core/hle/service/nwm/nwm_inf.cpp
@@ -7,14 +7,13 @@
 namespace Service {
 namespace NWM {
 
-const Interface::FunctionInfo FunctionTable[] = {
-    {0x000603C4, nullptr, "RecvBeaconBroadcastData"},
-    {0x00070742, nullptr, "ConnectToEncryptedAP"},
-    {0x00080302, nullptr, "ConnectToAP"},
-};
-
-NWM_INF::NWM_INF() {
-    Register(FunctionTable);
+NWM_INF::NWM_INF() : ServiceFramework("nwm::INF") {
+    static const FunctionInfo functions[] = {
+        {0x000603C4, nullptr, "RecvBeaconBroadcastData"},
+        {0x00070742, nullptr, "ConnectToEncryptedAP"},
+        {0x00080302, nullptr, "ConnectToAP"},
+    };
+    RegisterHandlers(functions);
 }
 
 } // namespace NWM
diff --git a/src/core/hle/service/nwm/nwm_inf.h b/src/core/hle/service/nwm/nwm_inf.h
index 0043d769c..2fdbfbfcb 100644
--- a/src/core/hle/service/nwm/nwm_inf.h
+++ b/src/core/hle/service/nwm/nwm_inf.h
@@ -9,13 +9,9 @@
 namespace Service {
 namespace NWM {
 
-class NWM_INF final : public Interface {
+class NWM_INF final : public ServiceFramework<NWM_INF> {
 public:
     NWM_INF();
-
-    std::string GetPortName() const override {
-        return "nwm::INF";
-    }
 };
 
 } // namespace NWM
diff --git a/src/core/hle/service/nwm/nwm_sap.cpp b/src/core/hle/service/nwm/nwm_sap.cpp
index fd29ed761..2621823df 100644
--- a/src/core/hle/service/nwm/nwm_sap.cpp
+++ b/src/core/hle/service/nwm/nwm_sap.cpp
@@ -7,13 +7,12 @@
 namespace Service {
 namespace NWM {
 
-/*
-const Interface::FunctionInfo FunctionTable[] = {
-};
-*/
-
-NWM_SAP::NWM_SAP() {
-    // Register(FunctionTable);
+NWM_SAP::NWM_SAP() : ServiceFramework("nwm::SAP") {
+    /*
+    static const FunctionInfo functions[] = {
+    };
+    RegisterHandlers(functions);
+    */
 }
 
 } // namespace NWM
diff --git a/src/core/hle/service/nwm/nwm_sap.h b/src/core/hle/service/nwm/nwm_sap.h
index f692e06d4..ad163a585 100644
--- a/src/core/hle/service/nwm/nwm_sap.h
+++ b/src/core/hle/service/nwm/nwm_sap.h
@@ -9,13 +9,9 @@
 namespace Service {
 namespace NWM {
 
-class NWM_SAP final : public Interface {
+class NWM_SAP final : public ServiceFramework<NWM_SAP> {
 public:
     NWM_SAP();
-
-    std::string GetPortName() const override {
-        return "nwm::SAP";
-    }
 };
 
 } // namespace NWM
diff --git a/src/core/hle/service/nwm/nwm_soc.cpp b/src/core/hle/service/nwm/nwm_soc.cpp
index fdffcb925..eacc511cb 100644
--- a/src/core/hle/service/nwm/nwm_soc.cpp
+++ b/src/core/hle/service/nwm/nwm_soc.cpp
@@ -7,13 +7,12 @@
 namespace Service {
 namespace NWM {
 
-/*
-const Interface::FunctionInfo FunctionTable[] = {
-};
-*/
-
-NWM_SOC::NWM_SOC() {
-    // Register(FunctionTable);
+NWM_SOC::NWM_SOC() : ServiceFramework("nwm::SOC") {
+    /*
+    static const FunctionInfo functions[] = {
+    };
+    RegisterHandlers(functions);
+    */
 }
 
 } // namespace NWM
diff --git a/src/core/hle/service/nwm/nwm_soc.h b/src/core/hle/service/nwm/nwm_soc.h
index 594941d7e..38fd4ac1e 100644
--- a/src/core/hle/service/nwm/nwm_soc.h
+++ b/src/core/hle/service/nwm/nwm_soc.h
@@ -9,13 +9,9 @@
 namespace Service {
 namespace NWM {
 
-class NWM_SOC final : public Interface {
+class NWM_SOC final : public ServiceFramework<NWM_SOC> {
 public:
     NWM_SOC();
-
-    std::string GetPortName() const override {
-        return "nwm::SOC";
-    }
 };
 
 } // namespace NWM
diff --git a/src/core/hle/service/nwm/nwm_tst.cpp b/src/core/hle/service/nwm/nwm_tst.cpp
index 5f292e5db..33ef6f1cd 100644
--- a/src/core/hle/service/nwm/nwm_tst.cpp
+++ b/src/core/hle/service/nwm/nwm_tst.cpp
@@ -7,13 +7,12 @@
 namespace Service {
 namespace NWM {
 
-/*
-const Interface::FunctionInfo FunctionTable[] = {
-};
-*/
-
-NWM_TST::NWM_TST() {
-    // Register(FunctionTable);
+NWM_TST::NWM_TST() : ServiceFramework("nwm::TST") {
+    /*
+    static const FunctionInfo functions[] = {
+    };
+    RegisterHandlers(functions);
+    */
 }
 
 } // namespace NWM
diff --git a/src/core/hle/service/nwm/nwm_tst.h b/src/core/hle/service/nwm/nwm_tst.h
index 8deca3216..abbd56140 100644
--- a/src/core/hle/service/nwm/nwm_tst.h
+++ b/src/core/hle/service/nwm/nwm_tst.h
@@ -9,13 +9,9 @@
 namespace Service {
 namespace NWM {
 
-class NWM_TST final : public Interface {
+class NWM_TST final : public ServiceFramework<NWM_TST> {
 public:
     NWM_TST();
-
-    std::string GetPortName() const override {
-        return "nwm::TST";
-    }
 };
 
 } // namespace NWM
diff --git a/src/core/hle/service/nwm/nwm_uds.cpp b/src/core/hle/service/nwm/nwm_uds.cpp
index 36f403805..dc8cd42d1 100644
--- a/src/core/hle/service/nwm/nwm_uds.cpp
+++ b/src/core/hle/service/nwm/nwm_uds.cpp
@@ -11,6 +11,7 @@
 #include <mutex>
 #include <unordered_map>
 #include <vector>
+#include <cryptopp/osrng.h>
 #include "common/common_types.h"
 #include "common/logging/log.h"
 #include "core/core_timing.h"
@@ -23,6 +24,7 @@
 #include "core/hle/service/nwm/uds_beacon.h"
 #include "core/hle/service/nwm/uds_connection.h"
 #include "core/hle/service/nwm/uds_data.h"
+#include "core/hle/shared_page.h"
 #include "core/memory.h"
 #include "network/network.h"
 
@@ -1320,6 +1322,19 @@ NWM_UDS::NWM_UDS() : ServiceFramework("nwm::UDS") {
 
     beacon_broadcast_event =
         CoreTiming::RegisterEvent("UDS::BeaconBroadcastCallback", BeaconBroadcastCallback);
+
+    CryptoPP::AutoSeededRandomPool rng;
+    auto mac = SharedPage::DefaultMac;
+    // Keep the Nintendo 3DS MAC header and randomly generate the last 3 bytes
+    rng.GenerateBlock(static_cast<CryptoPP::byte*>(mac.data() + 3), 3);
+
+    if (auto room_member = Network::GetRoomMember().lock()) {
+        if (room_member->IsConnected()) {
+            mac = room_member->GetMacAddress();
+        }
+    }
+    SharedPage::SetMacAddress(mac);
+    SharedPage::SetWifiLinkLevel(SharedPage::WifiLinkLevel::BEST);
 }
 
 NWM_UDS::~NWM_UDS() {
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp
index 2cdc98dc8..e032e3a0a 100644
--- a/src/core/hle/service/service.cpp
+++ b/src/core/hle/service/service.cpp
@@ -251,7 +251,6 @@ void Init(std::shared_ptr<SM::ServiceManager>& sm) {
     NEWS::InstallInterfaces(*sm);
     NFC::InstallInterfaces(*sm);
     NIM::InstallInterfaces(*sm);
-    NWM::Init();
     PTM::InstallInterfaces(*sm);
     QTM::InstallInterfaces(*sm);