1. Why use android_dlopen_ext in the first_stage_entry function to force open /system/bin/app_process?
2. Why dlclose immediately after dlopen in second_stage_entry? Why do it?
// native/jni/zygisk/entry.cpp
static void first_stage_entry() {
android_logging();
ZLOGD("inject 1st stage\n");
char path[PATH_MAX];
char buf[256];
char *ld = getenv("LD_PRELOAD");
if (char *c = strrchr(ld, ':')) {
*c = '\0';
strlcpy(path, c + 1, sizeof(path));
setenv("LD_PRELOAD", ld, 1); // Restore original LD_PRELOAD
} else {
unsetenv("LD_PRELOAD");
strlcpy(path, ld, sizeof(path));
}
// Force the linker to load the library on top of ourselves, so we do not
// need to unmap the 1st stage library that was loaded with LD_PRELOAD.
int fd = xopen(path, O_RDONLY | O_CLOEXEC);
// Use fd here instead of path to make sure inode is the same as 2nd stage
snprintf(buf, sizeof(buf), "%d", fd);
setenv(MAGISKFD_ENV, buf, 1);
struct stat s{};
xfstat(fd, &s);
android_dlextinfo info {
.flags = ANDROID_DLEXT_FORCE_LOAD | ANDROID_DLEXT_USE_LIBRARY_FD,
.library_fd = fd,
};
// 通过 inode 在 maps 中搜索 /sbin/magisk(app_process) 对应的内存区域
auto [addr, size] = find_map_range(path, s.st_ino);
if (addr && size) {
// 下面使用 android_dlopen_ext 重复加载 /sbin/magisk,
// 通过 reserved_addr 强制覆盖内存.
info.flags |= ANDROID_DLEXT_RESERVED_ADDRESS;
info.reserved_addr = addr;
// The existing address is guaranteed to fit, as 1st stage and 2nd stage
// are exactly the same ELF (same inode). However, the linker could over
// estimate the required size and refuse to dlopen. The estimated size
// is not accurate so size the size to unlimited.
info.reserved_size = -1;
}
setenv(INJECT_ENV_2, "1", 1);
// Force dlopen ourselves to make ourselves dlclose-able.
// After this call, all global variables will be reset.
// 重复加载 /sbin/magisk 到内存, 覆盖之后全局变量将被重置
// 这里为什么要强制 dlopen? 只是为了以后可以使用 dlclose 释放 zygisk 吗????
android_dlopen_ext(path, RTLD_LAZY, &info);
}
Code:
// // native/jni/zygisk/entry.cpp
static void second_stage_entry() {
zygisk_logging();
ZLOGD("inject 2nd stage\n");
char path[PATH_MAX];
MAGISKTMP = getenv(MAGISKTMP_ENV);
int fd = parse_int(getenv(MAGISKFD_ENV));
snprintf(path, sizeof(path), "/proc/self/fd/%d", fd);
xreadlink(path, path, PATH_MAX);
android_dlextinfo info {
.flags = ANDROID_DLEXT_USE_LIBRARY_FD,
.library_fd = fd,
};
// 这里的dlopen并不会重新调用 zygisk_init, 这里是假的dlopen? 只是为了下一行的 dlclose?
// 为什么要这样做?
// Why do this?
self_handle = android_dlopen_ext(path, RTLD_LAZY, &info);
dlclose(self_handle);
close(fd);
unsetenv(MAGISKTMP_ENV);
unsetenv(MAGISKFD_ENV);
sanitize_environ();
hook_functions();
}
Related
DFT_SSPL_MINI.c
Hi im sorry, this is decompiled
hi,what is this?
file extension c
tzacapaca said:
hi,what is this?
file extension c
Click to expand...
Click to collapse
Isn't that a file for VS2008 or higher with C-code? I'll check that for you
Checked that for you, and indeed it is decompiled C++. This is what it contains, but I don't know what we should do with this code? Maybe someone who knows C++ can make HSPL with this as a basis?
Code:
/* This file has been generated by the Hex-Rays decompiler.
Copyright (c) 2009 Hex-Rays <[email protected]>
Detected compiler: Visual C++
*/
#include <windows.h>
#include <defs.h>
//-------------------------------------------------------------------------
// Data declarations
extern char aGetprocesswind[]; // idb
extern char aGetuserobjecti[]; // idb
extern char aGetlastactivep[19]; // weak
extern char aGetactivewindo[16]; // weak
extern char aMessageboxa[]; // idb
extern char LibFileName[]; // idb
extern char aRomupdateutili[21]; // weak
extern char Caption[]; // idb
extern _UNKNOWN unk_409300; // weak
extern char Text[]; // idb
extern char aErrorDuringExt[]; // idb
extern _UNKNOWN unk_409400; // weak
extern _UNKNOWN unk_409408; // weak
extern int dword_40AA58; // weak
extern int dword_40ACA0; // weak
extern char off_40ACA4[92]; // idb
extern int dword_40AD10; // weak
extern int dword_40AD1C; // weak
extern int dword_40B2E0; // weak
extern int dword_40B2F0; // weak
extern int dword_40B308; // weak
extern int dword_40B30C; // weak
extern int dword_40B310; // weak
extern int dword_40B314; // weak
extern int dword_40B318; // weak
extern int dword_40B31C; // weak
extern int dword_40B320; // weak
extern int dword_40B324; // weak
extern CHAR Filename; // idb
extern char FileName[]; // idb
extern int dword_40BB68; // weak
//-------------------------------------------------------------------------
// Function declarations
#define __thiscall __cdecl // Test compile in C mode
// signed int __usercall sub_401000<eax>(int a1<eax>, int a2<edx>, int a3<ecx>);
LPVOID __cdecl sub_401050(DWORD NumberOfBytesWritten);
int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd);
// char *__cdecl strrchr(const char *, int);
signed int __cdecl sub_4017D5(int a1);
signed int __cdecl sub_40180C(int a1);
int (*__cdecl sub_40247B())(void);
int (*__cdecl sub_40249F())(void);
// _DWORD __cdecl _encode_pointer(_DWORD); weak
// int _encoded_null(void); weak
// _DWORD __cdecl _decode_pointer(_DWORD); weak
int __cdecl sub_402EE1(int a1);
// int __cdecl _invoke_watson(_DWORD, _DWORD, _DWORD, _DWORD, _DWORD); weak
// int __cdecl _invalid_parameter(_DWORD, _DWORD, _DWORD, _DWORD, _DWORD); weak
// int *__cdecl _errno();
int __cdecl sub_403325();
int __cdecl sub_4034EC(int a1);
int __cdecl sub_4034F6(int a1);
int __cdecl sub_4035D5(int a1);
int __cdecl sub_403601(int a1, int a2, int a3);
int __thiscall sub_40544A(void *this, char a2);
void __cdecl sub_4055AF();
// void *__cdecl memset(void *, int, size_t);
// _DWORD __thiscall __report_gsfailure(_DWORD ecx0, _BYTE _4); weak
// int __cdecl _unwind_handler(int, int, int, int, int); weak
// int __cdecl _abnormal_termination();
// HANDLE __stdcall CreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile);
// HRSRC __stdcall FindResourceA(HMODULE hModule, LPCSTR lpName, LPCSTR lpType);
// HGLOBAL __stdcall LoadResource(HMODULE hModule, HRSRC hResInfo);
// DWORD __stdcall WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds);
// BOOL __stdcall WriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped);
// DWORD __stdcall SizeofResource(HMODULE hModule, HRSRC hResInfo);
// BOOL __stdcall CreateProcessA(LPCSTR lpApplicationName, LPSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCSTR lpCurrentDirectory, LPSTARTUPINFOA lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation);
// BOOL __stdcall SetFileAttributesA(LPCSTR lpFileName, DWORD dwFileAttributes);
// LPVOID __stdcall LockResource(HGLOBAL hResData);
// DWORD __stdcall GetModuleFileNameA(HMODULE hModule, LPCH lpFilename, DWORD nSize);
// BOOL __stdcall CloseHandle(HANDLE hObject);
// BOOL __stdcall DeleteFileA(LPCSTR lpFileName);
// FARPROC __stdcall GetProcAddress(HMODULE hModule, LPCSTR lpProcName);
// HMODULE __stdcall LoadLibraryA(LPCSTR lpLibFileName);
// int __stdcall MessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType);
//----- (00401000) --------------------------------------------------------
signed int __usercall sub_401000<eax>(int a1<eax>, int a2<edx>, int a3<ecx>)
{
signed int result; // [email protected]
int v4; // [email protected]
int v5; // [email protected]
v5 = a1;
v4 = a3;
result = 0;
if ( a3 )
{
while ( *(_BYTE *)v5 )
{
*(_BYTE *)a2++ = *(_BYTE *)v5++;
--v4;
if ( !v4 )
{
result = -2147024774;
*(_BYTE *)(a2 - 1) = 0;
return result;
}
}
if ( !v4 )
{
--a2;
result = -2147024774;
}
*(_BYTE *)a2 = 0;
}
else
{
result = -2147024809;
}
return result;
}
//----- (00401050) --------------------------------------------------------
LPVOID __cdecl sub_401050(DWORD NumberOfBytesWritten)
{
HRSRC v1; // [email protected]
HRSRC v2; // [email protected]
LPVOID result; // [email protected]
HGLOBAL v4; // [email protected]
const void *v5; // [email protected]
HANDLE v6; // [email protected]
DWORD v7; // [email protected]
void *v8; // [email protected]
v1 = FindResourceA(0, (LPCSTR)(unsigned __int16)NumberOfBytesWritten, (LPCSTR)0xA);
v2 = v1;
if ( v1 && (v4 = LoadResource(0, v1)) != 0 )
{
result = LockResource(v4);
v5 = result;
if ( result )
{
v7 = SizeofResource(0, v2);
v6 = CreateFileA(FileName, 0x40000000u, 1u, 0, 2u, 2u, 0);
v8 = v6;
if ( v6 == (HANDLE)-1 )
{
result = 0;
}
else
{
WriteFile(v6, v5, v7, &NumberOfBytesWritten, 0);
CloseHandle(v8);
SetFileAttributesA(FileName, 2u);
result = (LPVOID)1;
}
}
}
else
{
result = 0;
}
return result;
}
//----- (004010F0) --------------------------------------------------------
int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
char *v4; // [email protected]
unsigned int v5; // [email protected]
unsigned int v6; // [email protected]
int v7; // [email protected]
signed int v8; // [email protected]
char v9; // [email protected]
int v10; // [email protected]
signed int v11; // [email protected]
char *v12; // [email protected]
int v13; // [email protected]
char *v14; // [email protected]
char v15; // [email protected]
int v16; // [email protected]
signed int v17; // [email protected]
int v18; // [email protected]
signed int v19; // [email protected]
char v20; // [email protected]
int v22; // [email protected]
signed int v23; // [email protected]
char *v24; // [email protected]
int v25; // [email protected]
char *v26; // [email protected]
char v27; // [email protected]
int v28; // [email protected]
signed int v29; // [email protected]
char *v30; // [email protected]
int v31; // [email protected]
char *v32; // [email protected]
char v33; // [email protected]
unsigned int v34; // [email protected]
int v35; // [email protected]
signed int v36; // [email protected]
char v37; // [email protected]
int v38; // [email protected]
signed int v39; // [email protected]
char *v40; // [email protected]
int v41; // [email protected]
char *v42; // [email protected]
char v43; // [email protected]
int v44; // [email protected]
signed int v45; // [email protected]
char *v46; // [email protected]
int v47; // [email protected]
char *v48; // [email protected]
char v49; // [email protected]
struct _PROCESS_INFORMATION ProcessInformation; // [sp+4h] [bp-54h]@64
struct _STARTUPINFOA StartupInfo; // [sp+14h] [bp-44h]@64
Filename = 0;
GetModuleFileNameA(0, &Filename, 0x1FFu);
v4 = strrchr(&Filename, 92);
if ( v4 )
*v4 = 0;
v5 = &Filename - FileName;
v6 = 0;
do
{
v8 = 512;
v7 = (int)FileName;
while ( 1 )
{
v9 = *(_BYTE *)(v5 + v7);
if ( !v9 )
break;
*(_BYTE *)v7++ = v9;
--v8;
if ( !v8 )
goto LABEL_9;
}
if ( v8 )
goto LABEL_10;
LABEL_9:
--v7;
LABEL_10:
*(_BYTE *)v7 = 0;
v11 = 512;
v10 = (int)FileName;
while ( *(_BYTE *)v10 )
{
++v10;
--v11;
if ( !v11 )
goto LABEL_23;
}
if ( v11 )
{
v13 = 512 - (512 - v11);
v12 = &FileName[512 - v11];
if ( 0 != v11 )
{
v14 = (char *)(&unk_409300 - (_UNKNOWN *)v12);
while ( 1 )
{
v15 = *(_BYTE *)((_DWORD)v14 + (_DWORD)v12);
if ( !v15 )
break;
*v12++ = v15;
--v13;
if ( !v13 )
goto LABEL_21;
}
if ( v13 )
goto LABEL_22;
LABEL_21:
--v12;
LABEL_22:
*v12 = 0;
}
}
LABEL_23:
v17 = 512;
v16 = (int)FileName;
while ( *(_BYTE *)v16 )
{
++v16;
--v17;
if ( !v17 )
goto LABEL_29;
}
if ( v17 )
sub_401000(*(_DWORD *)&off_40ACA4[v6], (int)&FileName[512 - v17], 512 - (512 - v17));
LABEL_29:
if ( !sub_401050(*(int *)((char *)&dword_40ACA0 + v6)) )
{
MessageBoxA(0, "Error during application start! Possible file corrupted!", Caption, 0x40010u);
return -1;
}
v6 += 8;
}
while ( v6 < 0x50 );
v19 = 512;
v18 = (int)FileName;
while ( 1 )
{
v20 = *(_BYTE *)(v5 + v18);
if ( !v20 )
break;
*(_BYTE *)v18++ = v20;
--v19;
if ( !v19 )
goto LABEL_37;
}
if ( v19 )
goto LABEL_38;
LABEL_37:
--v18;
LABEL_38:
*(_BYTE *)v18 = 0;
v23 = 512;
v22 = (int)FileName;
while ( *(_BYTE *)v22 )
{
++v22;
--v23;
if ( !v23 )
goto LABEL_51;
}
if ( v23 )
{
v25 = 512 - (512 - v23);
v24 = &FileName[512 - v23];
if ( 0 != v23 )
{
v26 = (char *)(&unk_409300 - (_UNKNOWN *)v24);
while ( 1 )
{
v27 = *(_BYTE *)((_DWORD)v26 + (_DWORD)v24);
if ( !v27 )
break;
*v24++ = v27;
--v25;
if ( !v25 )
goto LABEL_49;
}
if ( v25 )
goto LABEL_50;
LABEL_49:
--v24;
LABEL_50:
*v24 = 0;
}
}
LABEL_51:
v29 = 512;
v28 = (int)FileName;
while ( *(_BYTE *)v28 )
{
++v28;
--v29;
if ( !v29 )
goto LABEL_64;
}
if ( v29 )
{
v31 = 512 - (512 - v29);
v30 = &FileName[512 - v29];
if ( 0 != v29 )
{
v32 = (char *)("ROMUpdateUtility.exe" - v30);
while ( 1 )
{
v33 = *(_BYTE *)((_DWORD)v30 + (_DWORD)v32);
if ( !v33 )
break;
*v30++ = v33;
--v31;
if ( !v31 )
goto LABEL_62;
}
if ( v31 )
goto LABEL_63;
LABEL_62:
--v30;
LABEL_63:
*v30 = 0;
}
}
LABEL_64:
memset(&StartupInfo, 0, 0x44u);
if ( CreateProcessA(FileName, 0, 0, 0, 0, 0, 0, 0, &StartupInfo, &ProcessInformation)
&& (_DWORD)ProcessInformation.hProcess )
{
WaitForSingleObject(ProcessInformation.hProcess, 0xFFFFFFFFu);
CloseHandle(ProcessInformation.hProcess);
}
else
{
MessageBoxA(0, "Error during extraction! Possible file corrupted!", Caption, 0x40010u);
}
v34 = 0;
do
{
v36 = 512;
v35 = (int)FileName;
while ( 1 )
{
v37 = *(_BYTE *)(&Filename - FileName + v35);
if ( !v37 )
break;
*(_BYTE *)v35++ = v37;
--v36;
if ( !v36 )
goto LABEL_74;
}
if ( v36 )
goto LABEL_75;
LABEL_74:
--v35;
LABEL_75:
*(_BYTE *)v35 = 0;
v39 = 512;
v38 = (int)FileName;
while ( *(_BYTE *)v38 )
{
++v38;
--v39;
if ( !v39 )
goto LABEL_88;
}
if ( v39 )
{
v41 = 512 - (512 - v39);
v40 = &FileName[512 - v39];
if ( 0 != v39 )
{
v42 = (char *)(&unk_409300 - (_UNKNOWN *)v40);
while ( 1 )
{
v43 = *(_BYTE *)((_DWORD)v42 + (_DWORD)v40);
if ( !v43 )
break;
*v40++ = v43;
--v41;
if ( !v41 )
goto LABEL_86;
}
if ( v41 )
goto LABEL_87;
LABEL_86:
--v40;
LABEL_87:
*v40 = 0;
}
}
LABEL_88:
v45 = 512;
v44 = (int)FileName;
while ( *(_BYTE *)v44 )
{
++v44;
--v45;
if ( !v45 )
goto LABEL_101;
}
if ( v45 )
{
v47 = 512 - (512 - v45);
v46 = &FileName[512 - v45];
if ( 0 != v45 )
{
v48 = (char *)(*(_DWORD *)&off_40ACA4[v34] - (_DWORD)v46);
while ( 1 )
{
v49 = *(_BYTE *)((_DWORD)v46 + (_DWORD)v48);
if ( !v49 )
break;
*v46++ = v49;
--v47;
if ( !v47 )
goto LABEL_99;
}
if ( v47 )
goto LABEL_100;
LABEL_99:
--v46;
LABEL_100:
*v46 = 0;
}
}
LABEL_101:
SetFileAttributesA(FileName, 0x80u);
DeleteFileA(FileName);
v34 += 8;
}
while ( v34 < 0x50 );
return 0;
}
// 40ACA0: using guessed type int dword_40ACA0;
//----- (004017D5) --------------------------------------------------------
signed int __cdecl sub_4017D5(int a1)
{
signed int result; // [email protected]
if ( a1 && dword_40AD10 )
{
*(_DWORD *)a1 = dword_40AD10;
result = 0;
}
else
{
*_errno() = 22;
_invalid_parameter(0, 0, 0, 0, 0);
result = 22;
}
return result;
}
// 402FE7: using guessed type int __cdecl _invalid_parameter(_DWORD, _DWORD, _DWORD, _DWORD, _DWORD);
// 40AD10: using guessed type int dword_40AD10;
//----- (0040180C) --------------------------------------------------------
signed int __cdecl sub_40180C(int a1)
{
signed int result; // [email protected]
if ( a1 && dword_40AD10 )
{
*(_DWORD *)a1 = dword_40AD1C;
result = 0;
}
else
{
*_errno() = 22;
_invalid_parameter(0, 0, 0, 0, 0);
result = 22;
}
return result;
}
// 402FE7: using guessed type int __cdecl _invalid_parameter(_DWORD, _DWORD, _DWORD, _DWORD, _DWORD);
// 40AD10: using guessed type int dword_40AD10;
// 40AD1C: using guessed type int dword_40AD1C;
//----- (0040247B) --------------------------------------------------------
int (*__cdecl sub_40247B())(void)
{
int (*result)(void); // [email protected]
unsigned int v1; // [email protected]
result = (int (*)(void))&unk_409400;
v1 = (unsigned int)&unk_409400;
if ( &unk_409400 < &unk_409400 )
{
do
{
result = *(int (**)(void))v1;
if ( *(_DWORD *)v1 )
result = (int (*)(void))result();
v1 += 4;
}
while ( v1 < (unsigned int)&unk_409400 );
}
return result;
}
//----- (0040249F) --------------------------------------------------------
int (*__cdecl sub_40249F())(void)
{
int (*result)(void); // [email protected]
unsigned int v1; // [email protected]
result = (int (*)(void))&unk_409408;
v1 = (unsigned int)&unk_409408;
if ( &unk_409408 < &unk_409408 )
{
do
{
result = *(int (**)(void))v1;
if ( *(_DWORD *)v1 )
result = (int (*)(void))result();
v1 += 4;
}
while ( v1 < (unsigned int)&unk_409408 );
}
return result;
}
//----- (00402EE1) --------------------------------------------------------
int __cdecl sub_402EE1(int a1)
{
int result; // [email protected]
result = a1;
dword_40B2E0 = a1;
return result;
}
// 40B2E0: using guessed type int dword_40B2E0;
//----- (00403325) --------------------------------------------------------
int __cdecl sub_403325()
{
return _decode_pointer(dword_40B2F0);
}
// 40252F: using guessed type _DWORD __cdecl _decode_pointer(_DWORD);
// 40B2F0: using guessed type int dword_40B2F0;
//----- (004034EC) --------------------------------------------------------
int __cdecl sub_4034EC(int a1)
{
int result; // [email protected]
result = a1;
dword_40B308 = a1;
return result;
}
// 40B308: using guessed type int dword_40B308;
//----- (004034F6) --------------------------------------------------------
int __cdecl sub_4034F6(int a1)
{
int result; // [email protected]
result = a1;
dword_40B30C = a1;
return result;
}
// 40B30C: using guessed type int dword_40B30C;
//----- (004035D5) --------------------------------------------------------
int __cdecl sub_4035D5(int a1)
{
int result; // [email protected]
result = a1;
dword_40B310 = a1;
return result;
}
// 40B310: using guessed type int dword_40B310;
//----- (00403601) --------------------------------------------------------
int __cdecl sub_403601(int a1, int a2, int a3)
{
HMODULE v3; // [email protected]
HMODULE v4; // [email protected]
FARPROC v6; // [email protected]
FARPROC v7; // [email protected]
FARPROC v8; // [email protected]
FARPROC v9; // [email protected]
FARPROC v10; // [email protected]
int v11; // [email protected]
int v12; // [email protected]
int (__thiscall *v13)(_DWORD); // [email protected]
int v14; // [email protected]
int v15; // [email protected]
int (__thiscall *v16)(_DWORD, _DWORD, _DWORD, _DWORD, _DWORD, _DWORD); // [email protected]
int v17; // [email protected]
int (__thiscall *v18)(_DWORD); // [email protected]
int v19; // [email protected]
int v20; // [email protected]
int (__thiscall *v21)(_DWORD, _DWORD); // [email protected]
int v22; // [email protected]
int v23; // [email protected]
int (__thiscall *v24)(_DWORD, _DWORD, _DWORD, _DWORD, _DWORD); // [email protected]
int v25; // [email protected]
char v26; // [sp+10h] [bp-20h]@13
char v27; // [sp+18h] [bp-18h]@14
char v28; // [sp+1Ch] [bp-14h]@13
int v29; // [sp+20h] [bp-10h]@1
unsigned int v30; // [sp+24h] [bp-Ch]@1
int v31; // [sp+28h] [bp-8h]@1
int v32; // [sp+2Ch] [bp-4h]@1
v29 = _encoded_null();
v32 = 0;
v31 = 0;
v30 = 0;
if ( !dword_40B314 )
{
v3 = LoadLibraryA("USER32.DLL");
v4 = v3;
if ( !v3 || (v6 = GetProcAddress(v3, "MessageBoxA"), !v6) )
return 0;
dword_40B314 = _encode_pointer(v6);
v7 = GetProcAddress(v4, "GetActiveWindow");
dword_40B318 = _encode_pointer(v7);
v8 = GetProcAddress(v4, "GetLastActivePopup");
dword_40B31C = _encode_pointer(v8);
if ( sub_4017D5((int)&v31) )
_invoke_watson(0, 0, 0, 0, 0);
if ( v31 == 2 )
{
v9 = GetProcAddress(v4, "GetUserObjectInformationA");
dword_40B324 = _encode_pointer(v9);
if ( dword_40B324 )
{
v10 = GetProcAddress(v4, "GetProcessWindowStation");
dword_40B320 = _encode_pointer(v10);
}
}
}
v11 = v29;
if ( dword_40B320 == v29
|| dword_40B324 == v29
|| (v13 = (int (__thiscall *)(_DWORD))_decode_pointer(dword_40B320), (v12 = v13(v14)) != 0)
&& (v15 = v12,
v16 = (int (__thiscall *)(_DWORD, _DWORD, _DWORD, _DWORD, _DWORD, _DWORD))_decode_pointer(dword_40B324),
v16(v17, v15, 1, &v26, 12, &v28))
&& v27 & 1 )
{
if ( dword_40B318 != v11 )
{
v18 = (int (__thiscall *)(_DWORD))_decode_pointer(dword_40B318);
v32 = v18(v19);
if ( v32 )
{
if ( dword_40B31C != v11 )
{
v20 = v32;
v21 = (int (__thiscall *)(_DWORD, _DWORD))_decode_pointer(dword_40B31C);
v32 = v21(v22, v20);
}
}
}
}
else
{
if ( sub_40180C((int)&v30) )
_invoke_watson(0, 0, 0, 0, 0);
if ( v30 < 4 )
a3 |= 0x40000u;
else
a3 |= 0x200000u;
}
v23 = v32;
v24 = (int (__thiscall *)(_DWORD, _DWORD, _DWORD, _DWORD, _DWORD))_decode_pointer(dword_40B314);
return v24(v25, v23, a1, a2, a3);
}
// 4024C3: using guessed type _DWORD __cdecl _encode_pointer(_DWORD);
// 402526: using guessed type int _encoded_null(void);
// 40252F: using guessed type _DWORD __cdecl _decode_pointer(_DWORD);
// 402EEB: using guessed type int __cdecl _invoke_watson(_DWORD, _DWORD, _DWORD, _DWORD, _DWORD);
// 40B314: using guessed type int dword_40B314;
// 40B318: using guessed type int dword_40B318;
// 40B31C: using guessed type int dword_40B31C;
// 40B320: using guessed type int dword_40B320;
// 40B324: using guessed type int dword_40B324;
//----- (0040544A) --------------------------------------------------------
int __thiscall sub_40544A(void *this, char a2)
{
if ( this == (void *)dword_40AA58 )
__asm { rep retn }
return __report_gsfailure(this, a2);
}
// 406A85: using guessed type _DWORD __thiscall __report_gsfailure(_DWORD ecx0, _BYTE _4);
// 40AA58: using guessed type int dword_40AA58;
//----- (004055AF) --------------------------------------------------------
void __cdecl sub_4055AF()
{
dword_40BB68 = 0;
}
// 40BB68: using guessed type int dword_40BB68;
// ALL OK, 15 function(s) have been successfully decompiled
for hard spl you must to decompile spl first and than to reverse enginer it to make hard spl. I was try that but im not c++ or c programer
cardsharing said:
for hard spl you must to decompile spl first and than to reverse enginer it to make hard spl. I was try that but im not c++ or c programer
Click to expand...
Click to collapse
Me neither, I do C#
Hi. I want to ask some comparison problem in Android studio. I have implement a bluetooth data receiving code in Android studio to receive data from Arduino. If it receive "abcde", an audio should be play (mysound). But it can't play as expected. May I ask what is the problem in the below code? Thank you.
Arduino:
BT.println("abcde");
Android:
h = new Handler() {
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case RECIEVE_MESSAGE: // if receive massage
byte[ ] readBuf = (byte[ ]) msg.obj;
String strIncom = new String(readBuf, 0, msg.arg1); // create string from bytes array
sb.append(strIncom); // append string
int endOfLineIndex = sb.indexOf("\r\n"); // determine the end-of-line
//txtArduino.setText(strIncom);
if (endOfLineIndex > 0) { // if end-of-line,
String sbprint = sb.substring(0, endOfLineIndex); // extract string
sb.delete(0, sb.length()); // and clear
txtArduino.setText(sbprint); // update TextView
if(sbprint=="abcde"){
mySound.start();}
break;
}
};
};
Hi! I am currently doing on a project and I keep hitting the same error despite making changes. I have been hitting indexOutOfBound error and unable to delete my listView item because of that error. I am doing on Tab and Database. Can anyone help me with my error and problem? Thank you!!
java.lang.IndexOutOfBoundsException: Invalid index 0, size is 0
at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:255)
at java.util.ArrayList.get(ArrayList.java:308)
at itp231.dba.nyp.com.mabel_createchallenge.mabel_tabs.mabelUncompleted_Tab1$2.onClick(mabelUncompleted_Tab1.java:124)
at android.support.v7.app.AlertController$ButtonHandler.handleMessage(AlertController.java:157)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Here are by Java Codes
Code:
package itp231.dba.nyp.com.mabel_createchallenge;
import android.content.Context;
import android.database.Cursor;
import java.util.ArrayList;
import itp231.dba.nyp.com.mabel_createchallenge.mabel_database.mabel_MyDBAdpater;
/*
* Created by Guest Account on 13/7/2016.
*/
public class mabel_creatingChallengeApp {
private static mabel_creatingChallengeApp ourInstance = new mabel_creatingChallengeApp();
public static mabel_creatingChallengeApp getInstance() {
return ourInstance;
}
public mabel_creatingChallengeApp() {
challengesCreatedAL = new ArrayList<mabel_challenges>();
}
//* for mabelUncompleted_tab1.java */
private ArrayList<mabel_challenges> challengesCreatedAL;
public ArrayList<mabel_challenges> getArray() {
return challengesCreatedAL;
} //getting the array from ArrayList<mabel_challenges>
public ArrayList<mabel_challenges> getChallengesCreatedAL() {
return challengesCreatedAL;
}
//add and delete entries in the database
//add to database
//context --> context of current state of the application/object
//call it to get information regarding another part of your program (activity and package/application)
public static long addToDatabase(mabel_challenges challenges, Context c) {
mabel_MyDBAdpater db = new mabel_MyDBAdpater(c);
db.open();
long rowIDofInsertEntry = db.insertEntry(challenges);
db.close();
return rowIDofInsertEntry;
}
public static boolean deleteFromDatabase(int rowID, Context c) {
mabel_MyDBAdpater db = new mabel_MyDBAdpater(c);
db.open();
boolean updateStatus = db.removeEntry(rowID);
db.close();
return updateStatus;
}
public static boolean updateDatabase(mabel_challenges cc, int rowID, Context c) {
mabel_MyDBAdpater db = new mabel_MyDBAdpater(c);
db.open();
boolean updateStatus = db.updateEntry(rowID, cc);
db.close();
return updateStatus;
}
//populate array --> retrieve the array
//get the context --> get the content from the page
//store all retrieve data from database
public void populateArrayFromDB(Context c) {
challengesCreatedAL.clear();
mabel_MyDBAdpater db = new mabel_MyDBAdpater(c);
db.open();
Cursor cur = db.retrieveAllEntriesCursor();
cur.moveToFirst();
while(cur.moveToNext()) {
int rowID = cur.getInt(mabel_MyDBAdpater.COLUMN_KEY_ID);
String nameOfChallenge = cur.getString(mabel_MyDBAdpater.COLUMN_NAME_ID);
String descOfChallenge = cur.getString(mabel_MyDBAdpater.COLUMN_DESC_ID);
String durationOfChallenge = cur.getString(mabel_MyDBAdpater.COLUMN_DURATION_ID);
mabel_challenges newChallenge = new mabel_challenges(rowID, nameOfChallenge, descOfChallenge, durationOfChallenge);
challengesCreatedAL.add(newChallenge);
}
db.close();
}
}
Code:
package itp231.dba.nyp.com.mabel_createchallenge.mabel_tabs;
/*
fragment is part of an activity
*/
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v7.app.AlertDialog;
import android.view.ContextMenu;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.Toast;
import java.util.ArrayList;
import itp231.dba.nyp.com.mabel_createchallenge.R;
import itp231.dba.nyp.com.mabel_createchallenge.mabel_EditChallengeActivity;
import itp231.dba.nyp.com.mabel_createchallenge.mabel_challengeDetailActivity;
import itp231.dba.nyp.com.mabel_createchallenge.mabel_challenges;
import itp231.dba.nyp.com.mabel_createchallenge.mabel_creatingChallengeApp;
import itp231.dba.nyp.com.mabel_createchallenge.mabel_database.mabel_myChallengesListAdapter;
public class mabelUncompleted_Tab1 extends Fragment{
ListView listOfItemsLV;
ArrayList<mabel_challenges> challengesCreatedAL;
mabel_creatingChallengeApp cc;
public int selectedItem;
mabel_challenges c;
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.mabel_tab_1_uncompleted, container, false);
listOfItemsLV = (ListView) v.findViewById(R.id.challengesUncompletedLV);
registerForContextMenu(listOfItemsLV);
// addPage = (ImageButton) v.findViewById(R.id.addPage);
//calling out Instance Variable before the adapater
//to get challenges item on the list item
cc = mabel_creatingChallengeApp.getInstance();
//retrieve array from database
cc.populateArrayFromDB(getActivity().getApplicationContext()); //because is fragment so getActivity --> fragment is the contents in the tab -->getActivity will get the whole screen contents including contents in the tab
challengesCreatedAL = cc.getArray();
//Adapter for List View
mabel_myChallengesListAdapter challengesAdapter = new mabel_myChallengesListAdapter(getActivity(), challengesCreatedAL);
listOfItemsLV.setAdapter(challengesAdapter);
listOfItemsLV.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
//getting the position of item in the array list
mabel_challenges c = challengesCreatedAL.get(i);
//intent for challenge detail
//mabel_challengeDetailActivity.class --> get to here
Intent viewDetailsIntent = new Intent(getActivity().getApplicationContext(), mabel_challengeDetailActivity.class);
//put extra --> Add extended data to the intent
viewDetailsIntent.putExtra(mabel_challenges.INTENT_NAME_CHALLENGENAME, c.getName());
viewDetailsIntent.putExtra(mabel_challenges.INTENT_NAME_DESCRIPTION, c.getDesc());
viewDetailsIntent.putExtra(mabel_challenges.INTENT_NAME_DURATION, c.getDuration());
viewDetailsIntent.putExtra("position", i);
startActivity(viewDetailsIntent);
}
});
return v;
}
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
menu.setHeaderTitle("Options");
menu.add(1,1,1, "Edit");
menu.add(1,2,2, "Delete");
}
public boolean onContextItemSelected(MenuItem item) {
final AdapterView.AdapterContextMenuInfo menuInfo = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
selectedItem = menuInfo.position;
//mabel_challenges c = challengesCreatedAL.get(selectedItem);
switch(item.getItemId()) {
case 1:
//edit challenge
Intent editChallenge = new Intent (getActivity(), mabel_EditChallengeActivity.class);
editChallenge.putExtra(mabel_challenges.INTENT_NAME_ARRAY_ITEM, selectedItem);
startActivity(editChallenge);
break;
case 2:
//delete challenge
AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(getActivity());
dialogBuilder.setMessage("Confirm delete ?");
dialogBuilder.setPositiveButton("Delete" ,new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface dialogInterface, int i) {
mabel_myChallengesListAdapter challengeAdapter = new mabel_myChallengesListAdapter(getActivity().getApplicationContext(), challengesCreatedAL);
listOfItemsLV.setAdapter(challengeAdapter);
challengeAdapter.notifyDataSetChanged();
//prac 7b sales tracker -->delete the item
//selectedItem is the index of the array
mabel_creatingChallengeApp ca = mabel_creatingChallengeApp.getInstance();
int challengeId = ca.getArray().get(selectedItem).getId();
mabel_creatingChallengeApp.deleteFromDatabase(challengeId, getActivity().getApplicationContext());
ca.populateArrayFromDB(getActivity().getApplicationContext());
Toast.makeText(getActivity().getApplicationContext(), "Deleted!", Toast.LENGTH_LONG).show();
}
});
dialogBuilder.setNegativeButton("Cancel",new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface dialogInterface, int i) {
// dialogBuilder.setCancelable(true);
Toast.makeText(getActivity().getApplicationContext(), "Cancelled!", Toast.LENGTH_LONG).show();
}
});
dialogBuilder.create();
dialogBuilder.show();
break;
}
return true;
}
@Override
public void onResume() {
super.onResume();
cc.populateArrayFromDB(getActivity().getApplicationContext());
}
}
Code:
package itp231.dba.nyp.com.mabel_createchallenge.mabel_database;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
import itp231.dba.nyp.com.mabel_createchallenge.mabel_challenges;
import itp231.dba.nyp.com.mabel_createchallenge.mabel_creatingChallengeApp;
/**
* Created by Guest Account on 13/7/2016.
* for uncompleted Tab
*/
public class mabel_MyDBAdpater {
private static final String DATABASE_NAME = "Challenges.db"; //name of database
private static final String DATABASE_TABLE = "ChallengesDatabase"; //database table name
private static final int DATABASE_VERSION = 2;
private SQLiteDatabase _db; //sqlite database handler
private final Context context; //current context
public static final String KEY_ID = "_id";
public static final int COLUMN_KEY_ID = 0;
public static final String ENTRY_CHALLENGE_NAME = "Name"; //name of column
public static final int COLUMN_NAME_ID = 1; //retrieval, position
public static final String ENTRY_CHALLENGE_DESC = "Description";
public static final int COLUMN_DESC_ID = 2;
public static final String ENTRY_CHALLENGE_DURATION = "Duration";
public static final int COLUMN_DURATION_ID = 3;
protected static final String DATABASE_CREATE = "create table " + DATABASE_TABLE + " " + "(" + KEY_ID + " integer primary key autoincrement, " +
ENTRY_CHALLENGE_NAME + " Text, " + ENTRY_CHALLENGE_DESC + " Text, " + ENTRY_CHALLENGE_DURATION + " Text);";
//making debugging easier
//a fix pid for Eclipse debugger
//open and close method
private String mabel_MyDBAdapter_LOG_CAT = "MY_LOG";
private MyDBOpenHelper dbHelper;
public mabel_MyDBAdpater(Context _context)
{
this.context = _context;
dbHelper = new MyDBOpenHelper(context, DATABASE_NAME, null, DATABASE_VERSION); //help to create object
}
public void close()
{
_db.close();
Log.w(mabel_MyDBAdapter_LOG_CAT, "DB closed");
}
public void open() throws SQLiteException
{
try
{
_db = dbHelper.getWritableDatabase();
Log.w(mabel_MyDBAdapter_LOG_CAT, "DB opened as writable database");
}
catch(SQLiteException e)
{
_db = dbHelper.getReadableDatabase();
Log.w(mabel_MyDBAdapter_LOG_CAT, "DB opened as readable database");
}
}
public long insertEntry(mabel_challenges cc)
{
// Create a new record
ContentValues newEntryValues = new ContentValues();
// Assign values for each row
newEntryValues.put(ENTRY_CHALLENGE_NAME, cc.getName());
newEntryValues.put(ENTRY_CHALLENGE_DESC, cc.getDesc());
newEntryValues.put(ENTRY_CHALLENGE_DURATION, cc.getDuration());
// Insert the row
Log.w(mabel_MyDBAdapter_LOG_CAT, "Inserted EntryName = " + cc.getName()
+ " EntryDesc = " + cc.getDesc() + " EntryDuration = " + cc.getDuration() + " into table " + DATABASE_TABLE);
return _db.insert(DATABASE_TABLE, null, newEntryValues);
}
//removing data
public boolean removeEntry(long _rowIndex)
{
if (_db.delete(DATABASE_TABLE, KEY_ID + " = " + _rowIndex, null) <= 0)
{
Log.w(mabel_MyDBAdapter_LOG_CAT, "Removing entry where id = "
+ _rowIndex + " Failed");
return false;
}
Log.w(mabel_MyDBAdapter_LOG_CAT, "Removing entry where id = "
+ _rowIndex + " Success");
return true;
}
//update method
public boolean updateEntry(long rowIndex, mabel_challenges cc) {
ContentValues updateValues = new ContentValues();
mabel_creatingChallengeApp ca = mabel_creatingChallengeApp.getInstance();
updateValues.put(ENTRY_CHALLENGE_NAME, cc.getName());
updateValues.put(ENTRY_CHALLENGE_DESC, cc.getDesc());
updateValues.put(ENTRY_CHALLENGE_DURATION, cc.getDuration());
String where = KEY_ID + "=" + rowIndex; //selected id for updating data
Log.w(mabel_MyDBAdapter_LOG_CAT, "Updated Challenge Name = " + cc.getName() + "Update Challenge Description = " + cc.getDesc() + "Update Duration = " + cc.getDuration() + " into table " +DATABASE_TABLE);
if (_db.update(DATABASE_TABLE, updateValues, where, null) <= 0) {
return true; //return success
}
return false; //newer update anything
}
//retrieve method
public Cursor retrieveAllEntriesCursor()
{
Cursor c = null;
try
{
c = _db.query(DATABASE_TABLE, new String[] {KEY_ID,ENTRY_CHALLENGE_NAME, ENTRY_CHALLENGE_DESC, ENTRY_CHALLENGE_DURATION}, null, null, null, null, null);
}
catch(SQLiteException e)
{
Log.w(mabel_MyDBAdapter_LOG_CAT, "Retrieve fail!");
}
return c;
}
public class MyDBOpenHelper extends SQLiteOpenHelper
{
public MyDBOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version)
{
super(context, name, factory, version);
// TODO Auto-generated constructor stub
}
@Override //compulsory method
public void onCreate(SQLiteDatabase db)
{
// TODO Auto-generated method stub
db.execSQL(DATABASE_CREATE);
Log.w(mabel_MyDBAdapter_LOG_CAT, "Helper : DB " + DATABASE_TABLE + " Created!!");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
{
// TODO Auto-generated method stub
}
} // End of myDBOpenHelper
}
Can help me to see what's wrong? Thank you !!!!
I can't read the all code, it's too long, but ai think that you want to access for example array [5], but array length is smaller.
Trimis de pe al meu Sony Z2 D6503
mabelll said:
Hi! I am currently doing on a project and I keep hitting the same error despite making changes. I have been hitting indexOutOfBound error and unable to delete my listView item because of that error. I am doing on Tab and Database. Can anyone help me with my error and problem? Thank you!!
Click to expand...
Click to collapse
Uncompleted_Tab1 onClick(mabelUncompleted _Tab1.java:124)
cannot see the line number. check line 124 for yourself.
Hi there,
I have an issue with writing my app. I want to obtain the data (as shown below) and get the corresponding value from it. When I run my app on the emulator it crashes when I click the button, precisely on this line:
Code:
JSONObject jsonObject = json.getJSONObject(0);
Can someone at least, please skim through and let me know what I could be doing wrong. It must be something simple, because I am not trying to break into CIA from my phone.
This is a data from the link:
HTML:
// [ { "id": "304466804484872" ,"t" : "GOOG" ,"e" : "NASDAQ" ,"l" : "759.66" ,"l_fix" : "759.66" ,"l_cur" : "759.66" ,"s": "0" ,"ltt":"4:00PM EDT" ,"lt" : "Sep 9, 4:00PM EDT" ,"lt_dts" : "2016-09-09T16:00:03Z" ,"c" : "-15.66" ,"c_fix" : "-15.66" ,"cp" : "-2.02" ,"cp_fix" : "-2.02" ,"ccol" : "chr" ,"pcls_fix" : "775.32" } ]
Here is my class:
Code:
public JSONArray getJson(String url){
// Read response to string
HttpURLConnection connection = null;
BufferedReader reader = null;
try {
URL Url = new URL(url);
connection = (HttpURLConnection) Url.openConnection();
connection.connect();
InputStream stream = connection.getInputStream();
reader = new BufferedReader(new InputStreamReader(stream));
StringBuilder sb = new StringBuilder();
String line = "";
while ((line = reader.readLine()) != null) {
sb.append(line+"\n");
}
is.close();
result = sb.toString();
} catch(Exception e) {
return null;
}
// Convert string to object
try {
String token[] = result.split("//");
JSONArray jarr = new JSONArray (token[1]);
} catch(JSONException e){
return null;
}
return jarr;
}
This is how I use it on a click of a button:
Code:
quotebutton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// Constructing a URL
String urlprefix = "http://finance.google.com/finance/info?client=ig&q=";
String Symbol = editTextSymbol.getText().toString();
String Exchange = editTextExchange.getText().toString();
String url = urlprefix + Exchange + ":" + Symbol;
JSONArray json = getJson(url);
try {
JSONObject jsonObject = json.getJSONObject(0);
String id = jsonObject.getString("id");
EditTextQuoteTime.setText(id);
} catch (JSONException e){
EditTextQuoteTime.setText("ERROR");
}
//try {
// String id = json.getString("id");
// EditTextQuoteTime.setText(id);
//} catch (JSONException e){
// EditTextQuoteTime.setText("ERROR");
// }
}
});
I know I may have asked a question that is widely available online, but most of the posts are from the time before which the libraries were updated and parsing from the URL changed. Most of the posts are slightly different and I feel I am missing something.
I think I have a main problem with decoding the actual JSON string which is shown in the HTML above. I don't know how to omit the first few signs and then get my string from there. Can anyone help, please?
Have you ever tried to extend your favorite app with new features using Xposed, but were shocked halfway that your hooked app doesn't declare a permission in AndroidManifest ? And then you spent infinite hours on the internet trying to solve this frustrating problem, you decided to use services and an external intent, but you found out that it was not convenient, and finally you gave up...
So you are like me, who wasted hours looking for a solution, until I figured out how to do it myself. Here's a snippet to save time for future Xposed enthusiasts. Put this code snippet in handleLoadPackage
Java:
// Hook will only patch System Framework
if (!lpparam.packageName.equals("android")) return;
String targetPkgName = "com.example.app"; // Replace this with the target app package name
String[] newPermissions = new String[] { // Put the new permissions here
"android.permission.INTERNET",
"android.permission.ACCESS_NETWORK_STATE"
};
String grantPermissionsMethod = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
grantPermissionsMethod = "restorePermissionState";
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.S_V2) {
XposedBridge.log("[WARNING] THIS HOOK IS NOT GUARANTEED TO WORK ON ANDROID VERSIONS NEWER THAN ANDROID 12");
}
} else if (Build.VERSION.SDK_INT == Build.VERSION_CODES.P) {
grantPermissionsMethod = "grantPermissions";
}
else {
grantPermissionsMethod = "grantPermissionsLPw";
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
XposedBridge.log("[WARNING] THIS HOOK IS NOT GUARANTEED TO WORK ON ANDROID VERSIONS PRIOR TO JELLYBEAN");
}
}
XposedBridge.hookAllMethods(XposedHelpers.findClass("com.android.server.pm.permission.PermissionManagerService", lpparam.classLoader),
grantPermissionsMethod, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
// on Android R and above, param.args[0] is an instance of android.content.pm.parsing.ParsingPackageImpl
// on Android Q and older, param.args[0] is an instance of android.content.pm.PackageParser$Package
// However, they both declare the same fields we need, so no need to check for class type
String pkgName = (String) XposedHelpers.getObjectField(param.args[0], "packageName");
XposedBridge.log("Package " + pkgName + " is requesting permissions");
if (pkgName.equals(targetPkgName)) {
List<String> permissions = (List<String>) XposedHelpers.getObjectField(param.args[0], "requestedPermissions");
for (String newPermission: newPermissions) {
if (!permissions.contains(newPermission)) {
permissions.add(newPermission);
XposedBridge.log("Added " + newPermission + " permission to " + pkgName);
}
}
}
}
});
Notes:
You must check System Framework in LSposed Manager
A reboot is required after adding the target permissions
You still need to prompt the user to accept sensitive permissions (ie android.permission.READ_CONTACTS), even if you have added them using this method
Wow, thx. Great for the install permissions!
I wrote a class to grant install and runtime/sensitive permissions (without prompting users).
Android 12 and 13 implementation:
Java:
public class Grant_Package_Permissions {
private static final int sdk = android.os.Build.VERSION.SDK_INT;
public static void hook(LoadPackageParam lpparam) {
try {
Class<?> PermissionManagerService = XposedHelpers.findClass(
sdk >= 33 /* android 13+ */ ?
"com.android.server.pm.permission.PermissionManagerServiceImpl" :
"com.android.server.pm.permission.PermissionManagerService", lpparam.classLoader);
Class<?> AndroidPackage = XposedHelpers.findClass(
"com.android.server.pm.parsing.pkg.AndroidPackage", lpparam.classLoader);
Class<?> PermissionCallback = XposedHelpers.findClass(
sdk >= 33 /* android 13+ */ ?
"com.android.server.pm.permission.PermissionManagerServiceImpl$PermissionCallback" :
"com.android.server.pm.permission.PermissionManagerService$PermissionCallback", lpparam.classLoader);
// PermissionManagerService(Impl) - restorePermissionState
XposedHelpers.findAndHookMethod(PermissionManagerService, "restorePermissionState",
AndroidPackage, boolean.class, String.class, PermissionCallback, int.class, new XC_MethodHook() {
@SuppressWarnings("unchecked")
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
// params
Object pkg = param.args[0];
int filterUserId = (int) param.args[4];
// obtém os campos
Object mState = XposedHelpers.getObjectField(param.thisObject, "mState");
Object mRegistry = XposedHelpers.getObjectField(param.thisObject, "mRegistry");
Object mPackageManagerInt = XposedHelpers.getObjectField(param.thisObject, "mPackageManagerInt");
// Continua ?
String packageName = (String) XposedHelpers.callMethod(pkg, "getPackageName");
Object ps = XposedHelpers.callMethod(mPackageManagerInt,
sdk >= 33 /* android 13+ */ ?
"getPackageStateInternal" :
"getPackageSetting", packageName);
if (ps == null)
return;
int[] getAllUserIds = (int[]) XposedHelpers.callMethod(param.thisObject, "getAllUserIds");
int userHandle_USER_ALL = XposedHelpers.getStaticIntField(Class.forName("android.os.UserHandle"), "USER_ALL");
final int[] userIds = filterUserId == userHandle_USER_ALL ? getAllUserIds : new int[]{filterUserId};
for (int userId : userIds) {
List<String> requestedPermissions;
Object userState = XposedHelpers.callMethod(mState, "getOrCreateUserState", userId);
int appId = (int) XposedHelpers.callMethod(ps, "getAppId");
Object uidState = XposedHelpers.callMethod(userState, "getOrCreateUidState", appId);
// package 1
if (packageName.equals("PACKAGE_1")) {
requestedPermissions = (List<String>) XposedHelpers.callMethod(pkg, "getRequestedPermissions");
grantInstallOrRuntimePermission(requestedPermissions, uidState, mRegistry,
Manifest.permission.RECORD_AUDIO);
grantInstallOrRuntimePermission(requestedPermissions, uidState, mRegistry,
Manifest.permission.MODIFY_AUDIO_SETTINGS);
}
// package 2
if (packageName.equals("PACKAGE_2")) {
requestedPermissions = (List<String>) XposedHelpers.callMethod(pkg, "getRequestedPermissions");
grantInstallOrRuntimePermission(requestedPermissions, uidState, mRegistry,
Manifest.permission.READ_CONTACTS);
}
}
}
});
} catch (Exception e) {
XposedBridge.log(e);
}
}
private static void grantInstallOrRuntimePermission(List<String> requestedPermissions, Object uidState,
Object registry, String permission) {
if (!requestedPermissions.contains(permission))
XposedHelpers.callMethod(uidState, "grantPermission",
XposedHelpers.callMethod(registry, "getPermission", permission));
}
}
Edit: Android 12 and 13 implementation!
this looks promising. how to use this in xposed ? is there a module available?