{"id":400,"date":"2026-09-02T23:52:51","date_gmt":"2026-09-02T23:52:51","guid":{"rendered":"https:\/\/thered0ne.com\/?p=400"},"modified":"2026-09-02T23:55:31","modified_gmt":"2026-09-02T23:55:31","slug":"nokia-beacon-3-1-reverse-engineering-part-2","status":"publish","type":"post","link":"https:\/\/thered0ne.com\/?p=400","title":{"rendered":"Nokia Beacon 3.1: Reverse Engineering (Part 2)"},"content":{"rendered":"<div class=\"wp-block-image is-style-rounded\">\n<figure class=\"aligncenter size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"751\" height=\"648\" src=\"https:\/\/thered0ne.com\/wp-content\/uploads\/2026\/04\/Screenshot-2026-04-03-104508.png\" alt=\"Cute Nokia Router\" class=\"wp-image-352\" style=\"aspect-ratio:1;object-fit:cover;width:611px;height:auto\" srcset=\"https:\/\/thered0ne.com\/wp-content\/uploads\/2026\/04\/Screenshot-2026-04-03-104508.png 751w, https:\/\/thered0ne.com\/wp-content\/uploads\/2026\/04\/Screenshot-2026-04-03-104508-300x259.png 300w\" sizes=\"auto, (max-width: 751px) 100vw, 751px\" \/><\/figure>\n<\/div>\n\n\n<h1 class=\"wp-block-heading\">\ud83c\udfce\ufe0f\ud83d\udca8 Back to the future &#8211; Summary of part 1<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Part 1 demonstrated how root shell access was achieved on the Nokia Beacon 3.1 by physically extracting the NAND flash, dumping and analyzing the firmware, modifying it, and re-flashing it back to the device. The goal of that initial exploration was not simply to \u201cunlock\u201d the device, but to highlight the actual security boundaries enforced at the firmware and hardware level, and how those boundaries can be bypassed when physical access is assumed.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Several readers asked for a universal \u201croot password\u201d or a simple unlock method. That assumption is incorrect. There is no single shared root credential across devices. In ISP managed deployments like this, credentials are typically provisioned per-device and may be derived from manufacturing data or external provisioning systems controlled by the ISP or vendor infrastructure. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Administrative accounts (such as <strong>admin <\/strong>or <strong>superadmin<\/strong>) are separate, each governed by their own authentication mechanism and, in many cases, provisioned dynamically rather than being statically embedded in firmware. As a result, privilege escalation in this context is not about finding a generic password, but about understanding how trust is established between hardware, firmware, and provisioning systems.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In the comments from my previous article, many of you asked whether there is a simpler method to obtain shell access without the full hardware extraction process described in Part 1. The only alternative method identified involved is an exploitation of a vulnerability device, which could be used to execute system-level commands under specific conditions. However, this issue has since been addressed in the latest 2026 firmware release and is no longer exploitable on updated systems. The vulnerability is tracked as <a href=\"https:\/\/www.nokia.com\/we-are-nokia\/security\/product-security-advisory\/cve-2025-9974\/\">CVE-2025-9974<\/a> and was patched by the vendor.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The good news is, not all updates are pushed into all routers and maybe yours too. You have to check if it is vulnerable or not by following the procedure described later. Just cross your  fingers and stay with me\ud83e\udd1e\ud83c\udffb<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\u26a0\ufe0f <strong>Keeping your device without security update is dangerous. This write-up is provided for informational and security research purposes only. The vulnerability described has been patched by the vendor in recent firmware versions, and it is not exploitable on updated systems. The intent is to document the behavior of the system and the remediation process, not to provide a method for unauthorized access.<\/strong><\/p>\n\n\n\n<h1 class=\"wp-block-heading\">\ud83d\ude80 Disable Quagga shell &#8211; Hardware method: <\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">The Nokia Beacon 3.1 includes the <strong>Quagga shell<\/strong>, a restricted command-line environment intended for network administration rather than full system access. On my device, only the <strong>superadmin<\/strong> account provided access to this shell, and even then, the available commands were heavily restricted. While it is useful for basic diagnostics and configuration, it does not provide unrestricted access to the underlying operating system. That limitation is what motivated this research and the development of this method. <strong>This chapter it only applies to devices whose NAND firmware has already been modified as described in <a type=\"link\" href=\"https:\/\/thered0ne.com\/?p=351\" id=\"https:\/\/thered0ne.com\/?p=351\">Part 1.<\/a><\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In the previous article, I successfully obtained a root shell by modifying the firmware and replacing the system&#8217;s <code>init<\/code> process with <code>\/bin\/sh<\/code>. However, it came with a significant drawback: because the normal initialization process never started, essential services and background processes failed to launch. As a result, the router booted into a shell, but many of its networking and management features were unavailable.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span role=\"button\" tabindex=\"0\" style=\"color:#F8F8F2;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>&#91;   10.207898&#93; ubi0 warning: ubi_open_volume.part.0: cannot open device 0, volume 3, ret -16\n&#91;   10.313320&#93; VFS: Mounted root (squashfs filesystem) readonly on device 254:0.\n&#91;   10.320531&#93; Freeing unused kernel memory: 448K\n&#91;   10.361003&#93; Run \/bin\/sh as init process\n\n\nBusyBox v1.35.0 (2023-01-03 00:24:21 UTC) built-in shell (ash)\n\n\/bin\/sh: can't access tty; job control turned off\n\/ #<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki monokai\" style=\"background-color: #272822\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #F8F8F2\">&#91;   <\/span><span style=\"color: #AE81FF\">10.207898<\/span><span style=\"color: #F8F8F2\">&#93; ubi0 warning: ubi_open_volume.part.<\/span><span style=\"color: #AE81FF\">0<\/span><span style=\"color: #F8F8F2\">: cannot open device <\/span><span style=\"color: #AE81FF\">0<\/span><span style=\"color: #F8F8F2\">, volume <\/span><span style=\"color: #AE81FF\">3<\/span><span style=\"color: #F8F8F2\">, ret <\/span><span style=\"color: #F92672\">-<\/span><span style=\"color: #AE81FF\">16<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">&#91;   <\/span><span style=\"color: #AE81FF\">10.313320<\/span><span style=\"color: #F8F8F2\">&#93; VFS: Mounted <\/span><span style=\"color: #A6E22E\">root<\/span><span style=\"color: #F8F8F2\"> (squashfs filesystem) readonly on device <\/span><span style=\"color: #AE81FF\">254<\/span><span style=\"color: #F8F8F2\">:<\/span><span style=\"color: #AE81FF\">0.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">&#91;   <\/span><span style=\"color: #AE81FF\">10.320531<\/span><span style=\"color: #F8F8F2\">&#93; Freeing unused kernel memory: 448K<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">&#91;   <\/span><span style=\"color: #AE81FF\">10.361003<\/span><span style=\"color: #F8F8F2\">&#93; Run <\/span><span style=\"color: #F92672\">\/<\/span><span style=\"color: #F8F8F2\">bin<\/span><span style=\"color: #F92672\">\/<\/span><span style=\"color: #F8F8F2\">sh <\/span><span style=\"color: #F92672\">as<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #A6E22E; text-decoration: underline\">init<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #A6E22E; text-decoration: underline\">process<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">BusyBox v1.<\/span><span style=\"color: #AE81FF\">35.0<\/span><span style=\"color: #F8F8F2\"> (<\/span><span style=\"color: #AE81FF\">2023<\/span><span style=\"color: #F92672\">-<\/span><span style=\"color: #AE81FF\">01<\/span><span style=\"color: #F92672\">-<\/span><span style=\"color: #AE81FF\">03<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #AE81FF\">00<\/span><span style=\"color: #F8F8F2\">:<\/span><span style=\"color: #AE81FF\">24<\/span><span style=\"color: #F8F8F2\">:<\/span><span style=\"color: #AE81FF\">21<\/span><span style=\"color: #F8F8F2\"> UTC) built<\/span><span style=\"color: #F92672\">-in<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #A6E22E\">shell<\/span><span style=\"color: #F8F8F2\"> (ash)<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #F92672\">\/<\/span><span style=\"color: #F8F8F2\">bin<\/span><span style=\"color: #F92672\">\/<\/span><span style=\"color: #F8F8F2\">sh: can<\/span><span style=\"color: #E6DB74\">&#39;t access tty; job control turned of<\/span><span style=\"color: #F44747\">f<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F92672\">\/<\/span><span style=\"color: #F8F8F2\"> #<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Booting the router, disable quagga and start SSHd<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">To start the router, I executed the command <code>exec \/sbin\/init<\/code>. The problem is that it also starts the Quagga services, along with many other modules and processes that I don&#8217;t need. The normal boot process also overwrites the <code>secboot<\/code> flag that I patched in the first place. As a result, if I reboot the router, it automatically restores its original state, which disables the UART again.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The second important thing I do in this script is to create another script in <code>\/tmp<\/code> and I delay its execution. The script disables Quagga Shell, kills DropBear, removes root password from <code>\/mnt\/etc\/shadow<\/code>, create new keys and restart the Dropbear (SSHd)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>If you are willing to perform this part, I assume that you are already having a root shell in UART. I created a script that automate the booting if you are connected through UART, the link is below. Use `&#8211;help` for usage.<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/github.com\/warber0x\/NokiaBeacon3.1_Nand_Patcher\/blob\/main\/failsafeboot.py\">https:\/\/github.com\/warber0x\/NokiaBeacon3.1_Nand_Patcher\/blob\/main\/failsafeboot.py<\/a><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You have  to wait for 5 min. The router will boot, the web server will be up  and running and the SSH alive. If you face problems. Just leave a comment and I will check if I could help \ud83d\ude42  <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">All right !!! Your router is now really yours and you can inspect what ever you  want \ud83d\ude0e<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">P.S If you reboot the device yo must re-run the script again from the root shell through UART. There is no persistence for now&#8230;<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">\ud83d\udd13 Unlock your router &#8211; No UART, No Flash needed (Still in progress)<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">As mentioned above, this method only works on routers that have <strong>not<\/strong> been updated to the latest firmware. Your ISP may automatically install a firmware update, which will prevent this script from working. If you&#8217;re lucky, your router may still be running the older firmware. However, keep in mind that it will also remain vulnerable.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Don&#8217;t panic ! The attack still requires valid credentials. An attacker would first need access to your local network and then perform a man-in-the-middle (MITM) attack to capture your login credentials. To protect yourself, make sure HTTPS is enabled on your router.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This exploit only works on firmware version <strong>2502b.18.07.A17<\/strong>. Nokia addressed this vulnerability in security release <strong>BBDR2503<\/strong>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">To verify your router&#8217;s firmware version, open the router&#8217;s login page, press <strong>Ctrl+U<\/strong> to view the page source, and look for the following section:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"456\" height=\"144\" src=\"https:\/\/thered0ne.com\/wp-content\/uploads\/2026\/07\/image.png\" alt=\"\" class=\"wp-image-406\" srcset=\"https:\/\/thered0ne.com\/wp-content\/uploads\/2026\/07\/image.png 456w, https:\/\/thered0ne.com\/wp-content\/uploads\/2026\/07\/image-300x95.png 300w\" sizes=\"auto, (max-width: 456px) 100vw, 456px\" \/><\/figure>\n<\/div>\n\n\n<p class=\"wp-block-paragraph\">If you have firmware version <strong>2502<\/strong>, I have good and bad news for you.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The good news: you will be able to hack your own router.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The bad news: your router is vulnerable. However, as mentioned above, there is no reason to panic if you are the only person testing or attacking your own device.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">My tool executes commands directly on the router, disables <strong>Quagga<\/strong>, and enables the <strong>SSH service<\/strong> on port <strong>22<\/strong>. The only requirement is that you provide valid router credentials as parameters. Once authenticated, the tool can activate <strong>SSHD<\/strong> and disable the fu**ing <strong>Quagga shell<\/strong>. \ud83d\ude09<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong><font color=\"red\">The exploit is not ready yet. I&#8217;m working on it&#8230;<\/font><\/strong><\/h2>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span role=\"button\" tabindex=\"0\" style=\"color:#F8F8F2;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly># Run the tool\npython jailbreakBeacon.py admin &lt;YourPassword>\n\n# After that use the command to connect to ssh\nssh root@192.168.18.1<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki monokai\" style=\"background-color: #272822\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #F8F8F2\"># Run the tool<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">python jailbreakBeacon.py admin <\/span><span style=\"color: #F92672\">&lt;<\/span><span style=\"color: #F8F8F2\">YourPassword<\/span><span style=\"color: #F92672\">&gt;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\"># After that use the command to connect to ssh<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">ssh root@<\/span><span style=\"color: #AE81FF\">192.168<\/span><span style=\"color: #F8F8F2\">.<\/span><span style=\"color: #AE81FF\">18.1<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<h1 class=\"wp-block-heading\">\ud83e\udde9 Bonus : Dynamic Analysis (Reverse engineering)<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Expect In the part 3 the full exploitation and I will add another chapter on how to do some live debugging, dynamic analysis and reverse engineering of ARM binaries&#8230;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Thanks for reading and stay tuned folks \ud83d\ude09<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\ud83c\udfce\ufe0f\ud83d\udca8 Back to the future &#8211; Summary of part 1 Part 1 demonstrated how root shell access was achieved on the Nokia Beacon 3.1 by physically extracting the NAND flash, dumping and analyzing the firmware, modifying it, and re-flashing it back to the device. The goal of that initial exploration [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":352,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[14,20,5],"tags":[30,12,22],"class_list":["post-400","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-iot","category-reverse-engineering","category-security-research","tag-hardware-hacking","tag-iot","tag-reverse-engineering"],"_links":{"self":[{"href":"https:\/\/thered0ne.com\/index.php?rest_route=\/wp\/v2\/posts\/400","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/thered0ne.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/thered0ne.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/thered0ne.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/thered0ne.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=400"}],"version-history":[{"count":8,"href":"https:\/\/thered0ne.com\/index.php?rest_route=\/wp\/v2\/posts\/400\/revisions"}],"predecessor-version":[{"id":414,"href":"https:\/\/thered0ne.com\/index.php?rest_route=\/wp\/v2\/posts\/400\/revisions\/414"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/thered0ne.com\/index.php?rest_route=\/wp\/v2\/media\/352"}],"wp:attachment":[{"href":"https:\/\/thered0ne.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=400"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/thered0ne.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=400"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/thered0ne.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=400"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}