daily pastebin goal
12%
SHARE
TWEET

petithook.c

a guest Sep 24th, 2017 19 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2. *   This file is part of Luma3DS
  3. *   Copyright (C) 2016-2017 Aurora Wright, TuxSH
  4. *
  5. *   This program is free software: you can redistribute it and/or modify
  6. *   it under the terms of the GNU General Public License as published by
  7. *   the Free Software Foundation, either version 3 of the License, or
  8. *   (at your option) any later version.
  9. *
  10. *   This program is distributed in the hope that it will be useful,
  11. *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. *   GNU General Public License for more details.
  14. *
  15. *   You should have received a copy of the GNU General Public License
  16. *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
  17. *
  18. *   Additional Terms 7.b and 7.c of GPLv3 apply to this file:
  19. *       * Requiring preservation of specified reasonable legal notices or
  20. *         author attributions in that material or in the Appropriate Legal
  21. *         Notices displayed by works containing it.
  22. *       * Prohibiting misrepresentation of the origin of that material,
  23. *         or requiring that modified versions of such material be marked in
  24. *         reasonable ways as different from the original version.
  25. */
  26.  
  27. #include <3ds.h>
  28. #include <arpa/inet.h>
  29. #include "utils.h" // for makeARMBranch
  30. #include "minisoc.h"
  31. //#include "input_redirection.h"
  32. #include "menus.h"
  33. #include "petitcommemhook.h"
  34.  
  35. bool petithook_enabled = false;
  36. Handle petithookStartedEvent;
  37.  
  38. static MyThread petithookthread;
  39. static u8 ALIGN(8) petithookthreadStack[0x4000];
  40.  
  41. MyThread *petithookcreatethread(void)
  42. {
  43.     if(R_FAILED(MyThread_Create(&petithookthread, petithookthreadmain, petithookthreadStack, 0x4000, 0x20, CORE_SYSTEM)))
  44.         svcBreak(USERBREAK_PANIC);
  45.     return &petithookthread;
  46. }
  47.  
  48. //                       local hid,  local tsrd  localcprd,  localtswr,  localcpwr,  remote hid, remote ts,  remote circle
  49. static u32 hidData[] = { 0x00000FFF, 0x02000000, 0x007FF7FF, 0x00000000, 0x00000000, 0x00000FFF, 0x02000000, 0x007FF7FF };
  50. //                      remote ir
  51. static u32 irData[] = { 0x80800081 }; // Default: C-Stick at the center, no buttons.
  52.  
  53. int petithookstartresult;
  54.  
  55. void petithookthreadmain(void)
  56. {
  57.     Result res = 0;
  58.     res = miniSocInit();
  59.     if(R_FAILED(res))
  60.         return;
  61.  
  62.     int sock = socSocket(AF_INET, SOCK_DGRAM, 0);
  63.     while(sock == -1)
  64.     {
  65.         svcSleepThread(1000 * 0000 * 0000LL);
  66.         sock = socSocket(AF_INET, SOCK_DGRAM, 0);
  67.     }
  68.  
  69.     struct sockaddr_in saddr;
  70.     saddr.sin_family = AF_INET;
  71.     saddr.sin_port = htons(4950);
  72.     saddr.sin_addr.s_addr = gethostid();
  73.     res = socBind(sock, (struct sockaddr*)&saddr, sizeof(struct sockaddr_in));
  74.     if(res != 0)
  75.     {
  76.         socClose(sock);
  77.         miniSocExit();
  78.         inputRedirectionStartResult = res;
  79.         return;
  80.     }
  81.  
  82.     petithook_enabled = true;
  83.     svcSignalEvent(petithookthreadStartedEvent);
  84.  
  85.     u32 *hidDataPhys = PA_FROM_VA_PTR(hidData);
  86.     hidDataPhys += 5; // skip to +20
  87.  
  88.     u32 *irDataPhys = PA_FROM_VA_PTR(irData);
  89.  
  90.     char buf[20];
  91.     u32 oldSpecialButtons = 0, specialButtons = 0;
  92.     while(petithook_enabled && !terminationRequest)
  93.     {
  94.         struct pollfd pfd;
  95.         pfd.fd = sock;
  96.         pfd.events = POLLIN;
  97.         pfd.revents = 0;
  98.  
  99.         int pollres = socPoll(&pfd, 1, 10);
  100.         if(pollres > 0 && (pfd.revents & POLLIN))
  101.         {
  102.             int n = soc_recvfrom(sock, buf, 20, 0, NULL, 0);
  103.             if(n < 0)
  104.                 break;
  105.             else if(n < 12)
  106.                 continue;
  107.  
  108.             memcpy(hidDataPhys, buf, 12);
  109.             if(n >= 20)
  110.             {
  111.                 memcpy(irDataPhys, buf + 12, 4);
  112.  
  113.                 oldSpecialButtons = specialButtons;
  114.                 memcpy(&specialButtons, buf + 16, 4);
  115.  
  116.                 if(!(oldSpecialButtons & 1) && (specialButtons & 1)) // HOME button pressed
  117.                     srvPublishToSubscriber(0x204, 0);
  118.                 else if((oldSpecialButtons & 1) && !(specialButtons & 1)) // HOME button released
  119.                     srvPublishToSubscriber(0x205, 0);
  120.  
  121.                 if(!(oldSpecialButtons & 2) && (specialButtons & 2)) // POWER button pressed
  122.                     srvPublishToSubscriber(0x202, 0);
  123.  
  124.                 if(!(oldSpecialButtons & 4) && (specialButtons & 4)) // POWER button held long
  125.                     srvPublishToSubscriber(0x203, 0);
  126.             }
  127.         }
  128.     }
  129.  
  130.     struct linger linger;
  131.     linger.l_onoff = 1;
  132.     linger.l_linger = 0;
  133.  
  134.     socSetsockopt(sock, SOL_SOCKET, SO_LINGER, &linger, sizeof(struct linger));
  135.  
  136.     socClose(sock);
  137.     miniSocExit();
  138. }
  139.  
  140. void hidCodePatchFunc(void);
  141. void irCodePatchFunc(void);
  142.  
  143. Result InputRedirection_DoOrUndoPatches(void)
  144. {
  145.     s64 startAddress, textTotalRoundedSize, rodataTotalRoundedSize, dataTotalRoundedSize;
  146.     u32 totalSize;
  147.     Handle processHandle;
  148.  
  149.     Result res = OpenProcessByName("hid", &processHandle);
  150.  
  151.     if(R_SUCCEEDED(res))
  152.     {
  153.         svcGetProcessInfo(&textTotalRoundedSize, processHandle, 0x10002); // only patch .text + .data
  154.         svcGetProcessInfo(&rodataTotalRoundedSize, processHandle, 0x10003);
  155.         svcGetProcessInfo(&dataTotalRoundedSize, processHandle, 0x10004);
  156.  
  157.         totalSize = (u32)(textTotalRoundedSize + rodataTotalRoundedSize + dataTotalRoundedSize);
  158.  
  159.         svcGetProcessInfo(&startAddress, processHandle, 0x10005);
  160.         res = svcMapProcessMemoryEx(processHandle, 0x00100000, (u32) startAddress, totalSize);
  161.  
  162.         if(R_SUCCEEDED(res))
  163.         {
  164.             static const u32 hidOrigRegisterAndValue[] = { 0x1EC46000, 0x4001 };
  165.             static const u32 hidOrigCode[] = {
  166.                 0xE92D4070, // push {r4-r6, lr}
  167.                 0xE1A05001, // mov  r5, r1
  168.                 0xEE1D4F70, // mrc  p15, 0, r4, c13, c0, 3
  169.                 0xE3A01801, // mov  r1, #0x10000
  170.                 0xE5A41080, // str  r1, [r4,#0x80]!
  171.             };
  172.  
  173.             static u32 *hidRegPatchOffsets[2];
  174.             static u32 *hidPatchJumpLoc;
  175.  
  176.             if(petithook_enabled)
  177.             {
  178.                 memcpy(hidRegPatchOffsets[0], &hidOrigRegisterAndValue, sizeof(hidOrigRegisterAndValue));
  179.                 memcpy(hidRegPatchOffsets[1], &hidOrigRegisterAndValue, sizeof(hidOrigRegisterAndValue));
  180.                 memcpy(hidPatchJumpLoc, &hidOrigCode, sizeof(hidOrigCode));
  181.             }
  182.             else
  183.             {
  184.                 u32 hidDataPhys = (u32)PA_FROM_VA_PTR(hidData);
  185.                 u32 hidCodePhys = (u32)PA_FROM_VA_PTR(&hidCodePatchFunc);
  186.                 u32 hidHook[] = {
  187.                     0xE59F3004, // ldr r3,  [pc, #4]
  188.                     0xE59FC004, // ldr r12, [pc, #4]
  189.                     0xE12FFF1C, // bx  r12
  190.                     hidDataPhys,
  191.                     hidCodePhys,
  192.                 };
  193.  
  194.                 u32 *off = (u32 *)memsearch((u8 *)0x00100000, &hidOrigRegisterAndValue, totalSize, sizeof(hidOrigRegisterAndValue));
  195.                 if(off == NULL)
  196.                 {
  197.                     svcUnmapProcessMemoryEx(processHandle, 0x00100000, totalSize);
  198.                     return -1;
  199.                 }
  200.  
  201.                 u32 *off2 = (u32 *)memsearch((u8 *)off + sizeof(hidOrigRegisterAndValue), &hidOrigRegisterAndValue, totalSize - ((u32)off - 0x00100000), sizeof(hidOrigRegisterAndValue));
  202.                 if(off2 == NULL)
  203.                 {
  204.                     svcUnmapProcessMemoryEx(processHandle, 0x00100000, totalSize);
  205.                     return -2;
  206.                 }
  207.  
  208.                 u32 *off3 = (u32 *)memsearch((u8 *)0x00100000, &hidOrigCode, totalSize, sizeof(hidOrigCode));
  209.                 if(off3 == NULL)
  210.                 {
  211.                     svcUnmapProcessMemoryEx(processHandle, 0x00100000, totalSize);
  212.                     return -3;
  213.                 }
  214.  
  215.                 hidRegPatchOffsets[0] = off;
  216.                 hidRegPatchOffsets[1] = off2;
  217.                 hidPatchJumpLoc = off3;
  218.  
  219.                 *off = *off2 = hidDataPhys;
  220.                 memcpy(off3, &hidHook, sizeof(hidHook));
  221.             }
  222.         }
  223.  
  224.         res = svcUnmapProcessMemoryEx(processHandle, 0x00100000, totalSize);
  225.     }
  226.     svcCloseHandle(processHandle);
  227.  
  228.     res = OpenProcessByName("ir", &processHandle);
  229.     if(R_SUCCEEDED(res) && osGetKernelVersion() >= SYSTEM_VERSION(2, 44, 6))
  230.     {
  231.         svcGetProcessInfo(&textTotalRoundedSize, processHandle, 0x10002); // only patch .text + .data
  232.         svcGetProcessInfo(&rodataTotalRoundedSize, processHandle, 0x10003);
  233.         svcGetProcessInfo(&dataTotalRoundedSize, processHandle, 0x10004);
  234.  
  235.         totalSize = (u32)(textTotalRoundedSize + rodataTotalRoundedSize + dataTotalRoundedSize);
  236.  
  237.         svcGetProcessInfo(&startAddress, processHandle, 0x10005);
  238.         res = svcMapProcessMemoryEx(processHandle, 0x00100000, (u32) startAddress, totalSize);
  239.  
  240.         if(R_SUCCEEDED(res))
  241.         {
  242.             static bool useOldSyncCode;
  243.             static u32 irOrigReadingCode[5] = {
  244.                 0xE5940000, // ldr r0, [r4]
  245.                 0xE1A01005, // mov r1, r5
  246.                 0xE3A03005, // mov r3, #5
  247.                 0xE3A02011, // mov r2, #17
  248.                 0x00000000  // (bl i2c_read_raw goes here)
  249.             };
  250.  
  251.             static const u32 irOrigWaitSyncCode[] = {
  252.                 0xEF000024, // svc 0x24 (WaitSynchronization)
  253.                 0xE1B01FA0, // movs r1, r0, lsr#31
  254.                 0xE1A0A000, // mov r10, r0
  255.             }, irOrigWaitSyncCodeOld[] = {
  256.                 0xE0AC6000, // adc r6, r12, r0
  257.                 0xE5D70000, // ldrb r0, [r7]
  258.             }; // pattern for 8.1
  259.  
  260.             static const u32 irOrigCppFlagCode[] = {
  261.                 0xE3550000, // cmp r5, #0
  262.                 0xE3A0B080, // mov r11, #0x80
  263.             };
  264.  
  265.             static u32 *irHookLoc, *irWaitSyncLoc, *irCppFlagLoc;
  266.  
  267.             if(petithook_enabled)
  268.             {
  269.                 memcpy(irHookLoc, &irOrigReadingCode, sizeof(irOrigReadingCode));
  270.                 if(useOldSyncCode)
  271.                     memcpy(irWaitSyncLoc, &irOrigWaitSyncCodeOld, sizeof(irOrigWaitSyncCodeOld));
  272.                 else
  273.                     memcpy(irWaitSyncLoc, &irOrigWaitSyncCode, sizeof(irOrigWaitSyncCode));
  274.                 memcpy(irCppFlagLoc, &irOrigCppFlagCode, sizeof(irOrigCppFlagCode));
  275.             }
  276.             else
  277.             {
  278.                 u32 irDataPhys = (u32)PA_FROM_VA_PTR(irData);
  279.                 u32 irCodePhys = (u32)PA_FROM_VA_PTR(&irCodePatchFunc);
  280.  
  281.                 u32 irHook[] = {
  282.                     0xE5940000, // ldr r0, [r4]
  283.                     0xE1A01005, // mov r1, r5
  284.                     0xE59FC000, // ldr r12, [pc] (actually +8)
  285.                     0xE12FFF3C, // blx r12
  286.                     irCodePhys,
  287.                 };
  288.  
  289.                 u32 *off = (u32 *)memsearch((u8 *)0x00100000, &irOrigReadingCode, totalSize, sizeof(irOrigReadingCode) - 4);
  290.                 if(off == NULL)
  291.                 {
  292.                     svcUnmapProcessMemoryEx(processHandle, 0x00100000, totalSize);
  293.                     return -4;
  294.                 }
  295.  
  296.                 u32 *off2 = (u32 *)memsearch((u8 *)0x00100000, &irOrigWaitSyncCode, totalSize, sizeof(irOrigWaitSyncCode));
  297.                 if(off2 == NULL)
  298.                 {
  299.                     off2 = (u32 *)memsearch((u8 *)0x00100000, &irOrigWaitSyncCodeOld, totalSize, sizeof(irOrigWaitSyncCodeOld));
  300.                     if(off2 == NULL)
  301.                     {
  302.                         svcUnmapProcessMemoryEx(processHandle, 0x00100000, totalSize);
  303.                         return -5;
  304.                     }
  305.  
  306.                     useOldSyncCode = true;
  307.                 }
  308.                 else
  309.                     useOldSyncCode = false;
  310.  
  311.                 u32 *off3 = (u32 *)memsearch((u8 *)0x00100000, &irOrigCppFlagCode, totalSize, sizeof(irOrigCppFlagCode));
  312.                 if(off3 == NULL)
  313.                 {
  314.                     svcUnmapProcessMemoryEx(processHandle, 0x00100000, totalSize);
  315.                     return -6;
  316.                 }
  317.  
  318.                 *(void **)(irCodePhys + 8) = decodeARMBranch(off + 4);
  319.                 *(void **)(irCodePhys + 12) = (void*)irDataPhys;
  320.  
  321.                 irHookLoc = off;
  322.                 irWaitSyncLoc = off2;
  323.                 irCppFlagLoc = off3;
  324.  
  325.                 irOrigReadingCode[4] = off[4]; // Copy the branch.
  326.  
  327.                 memcpy(irHookLoc, &irHook, sizeof(irHook));
  328.  
  329.                 // This "NOP"s out a WaitSynchronisation1 (on the event bound to the 'IR' interrupt) or the check of a previous one
  330.                 *irWaitSyncLoc = 0xE3A00000; // mov r0, #0
  331.  
  332.                 // This NOPs out a flag check in ir:user's CPP emulation
  333.                 *irCppFlagLoc = 0xE3150000; // tst r5, #0
  334.             }
  335.         }
  336.  
  337.         res = svcUnmapProcessMemoryEx(processHandle, 0x00100000, totalSize);
  338.     }
  339.     svcCloseHandle(processHandle);
  340.  
  341.     return res;
  342. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top