/* * Testing whether the current process is getting the focus. * * See frameworks/base/core/java/android/view/IWindow.aidl and * frameworks/base/services/java/com/android/server/WindowManagerService.java * for more details. */ private static bool GainingWindowFocus(Thread current, binder_transaction_data tr) { const int OP_windowFocusChanged = 5; if (tr.code != OP_windowFocusChanged || tr.data_size != 0x3c) { return(false); } var buf = InspectionBuffer; tr.data_buffer.Read(current, buf); bool header_matched = true; for (var i = 0; i < WindowFocusChangedHeader.Length && header_matched; ++i) { if (buf[i] != WindowFocusChangedHeader[i]) { header_matched = false; } } if (!header_matched) { return(false); } int get_focus; (tr.data_buffer + WindowFocusChangedHeader.Length).Read(current, out get_focus); return(get_focus == 1); }
/* * Heuristic for determing whether a transaction is mapping the screen buffer * into the process. * * See frameworks/base/libs/ui/GraphicBuffer.cpp for more details. */ private static bool IsScreenSharingTransaction(Thread current, ref binder_transaction_data tr) { int a0, a1, a2; const uint SystemEuid = 1000; if (tr.sender_euid != SystemEuid || tr.data_size != 0x54 || tr.offsets_size != 4) { return(false); } tr.data_buffer.Read(current, out a0); (tr.data_buffer + sizeof(int)).Read(current, out a1); (tr.data_buffer + sizeof(int) * 2).Read(current, out a2); return(a0 == 0x3c && a1 == 0x1 && a2 == 0x47424652); }
/* * Testing whether the current process is getting the focus. * * See frameworks/base/core/java/android/view/IWindow.aidl and * frameworks/base/services/java/com/android/server/WindowManagerService.java * for more details. */ private static bool GainingWindowFocus(Thread current, binder_transaction_data tr) { const int OP_windowFocusChanged = 5; if (tr.code != OP_windowFocusChanged || tr.data_size != 0x3c) return false; var buf = InspectionBuffer; tr.data_buffer.Read(current, buf, buf.Length); bool header_matched = true; for (var i = 0; i < WindowFocusChangedHeader.Length && header_matched; ++i) { if (buf[i] != WindowFocusChangedHeader[i]) header_matched = false; } if (!header_matched) return false; int get_focus; (tr.data_buffer + WindowFocusChangedHeader.Length).Read(current, out get_focus); return get_focus == 1; }
private static int PatchReadTransaction(Thread current, Pointer marshaledBufferStart, ref binder_transaction_data tr) { if (tr.data_size != 0) tr.data_buffer += current.Parent.binderVMStart.Value.ToUInt32(); if (tr.offsets_size != 0) tr.data_offsets += current.Parent.binderVMStart.Value.ToUInt32(); if (GainingWindowFocus(current, tr)) Globals.SecurityManager.OnActiveProcessChanged(current.Parent); for (var off_ptr = tr.data_offsets; off_ptr < tr.data_offsets + tr.offsets_size; off_ptr += 4) { var fp = new flat_binder_object(); int off; if (off_ptr.Read(current, out off) != 0) { Arch.Console.Write("Can't get offset"); return -1; } var fp_ptr = tr.data_buffer + off; if (fp_ptr.Read(current, out fp) != 0) { Arch.Console.Write("Read fp failed, ptr:"); Arch.Console.Write(fp_ptr.Value.ToInt32()); Arch.Console.WriteLine(); return -1; } //Arch.Console.Write("off_ptr:"); //Arch.Console.Write(tr->data_offsets.Value.ToUInt32()); //Arch.Console.Write(" Off end:"); //Arch.Console.Write((tr->data_offsets + tr->offsets_size).Value.ToUInt32()); //Arch.Console.WriteLine(); switch (fp.type) { case BinderINode.BINDER_TYPE_FD: { var proc = current.Parent; var linux_fd = fp.binderOrHandle.Value.ToInt32(); GenericINode inode; if (IsScreenSharingTransaction(current, ref tr)) inode = new ScreenBufferINode(linux_fd, proc.helperPid); else inode = new BinderSharedINode(linux_fd, proc.helperPid); int fd = proc.GetUnusedFd(); proc.InstallFd(fd, new File(proc, inode, FileSystem.O_RDWR, 0)); // Patch the data structure (fp_ptr + flat_binder_object.OFFSET_OF_HANDLE).Write(current, fd); } break; case BinderINode.BINDER_TYPE_HANDLE: // sliently ignore it (it seems safe) break; default: Arch.Console.Write("BinderINode::PatchReadTransaction ignoring "); Arch.Console.Write(fp.type); Arch.Console.WriteLine(); break; } } return 0; }
/* * Heuristic for determing whether a transaction is mapping the screen buffer * into the process. * * See frameworks/base/libs/ui/GraphicBuffer.cpp for more details. */ private static bool IsScreenSharingTransaction(Thread current, ref binder_transaction_data tr) { int a0, a1, a2; const uint SystemEuid = 1000; if (tr.sender_euid != SystemEuid || tr.data_size != 0x54 || tr.offsets_size != 4) return false; tr.data_buffer.Read(current, out a0); (tr.data_buffer + sizeof(int)).Read(current, out a1); (tr.data_buffer + sizeof(int) * 2).Read(current, out a2); return a0 == 0x3c && a1 == 0x1 && a2 == 0x47424652; }
private static int PatchReadTransaction(Thread current, Pointer marshaledBufferStart, ref binder_transaction_data tr) { Contract.Requires(current.Parent != null); if (tr.data_size != 0) { tr.data_buffer += current.Parent.binderVMStart.Value.ToUInt32(); } if (tr.offsets_size != 0) { tr.data_offsets += current.Parent.binderVMStart.Value.ToUInt32(); } if (GainingWindowFocus(current, tr)) { Globals.SecurityManager.OnActiveProcessChanged(current.Parent); } for (var off_ptr = tr.data_offsets; off_ptr < tr.data_offsets + tr.offsets_size; off_ptr += 4) { var fp = new flat_binder_object(); int off; if (off_ptr.Read(current, out off) != 0) { Arch.Console.Write("Can't get offset"); return(-1); } var fp_ptr = tr.data_buffer + off; if (fp_ptr.Read(current, out fp) != 0) { Arch.Console.Write("Read fp failed, ptr:"); Arch.Console.Write(fp_ptr.Value.ToInt32()); Arch.Console.WriteLine(); return(-1); } //Arch.Console.Write("off_ptr:"); //Arch.Console.Write(tr->data_offsets.Value.ToUInt32()); //Arch.Console.Write(" Off end:"); //Arch.Console.Write((tr->data_offsets + tr->offsets_size).Value.ToUInt32()); //Arch.Console.WriteLine(); switch (fp.type) { case BinderINode.BINDER_TYPE_FD: { var proc = current.Parent; var linux_fd = fp.binderOrHandle.Value.ToInt32(); GenericINode inode; if (IsScreenSharingTransaction(current, ref tr)) { inode = new ScreenBufferINode(linux_fd, proc.helperPid); } else { inode = new BinderSharedINode(linux_fd, proc.helperPid); } int fd = proc.GetUnusedFd(); proc.InstallFd(fd, new File(proc, inode, FileSystem.O_RDWR, 0)); // Patch the data structure (fp_ptr + flat_binder_object.OFFSET_OF_HANDLE).Write(current, fd); } break; case BinderINode.BINDER_TYPE_HANDLE: // sliently ignore it (it seems safe) break; default: Arch.Console.Write("BinderINode::PatchReadTransaction ignoring "); Arch.Console.Write(fp.type); Arch.Console.WriteLine(); break; } } return(0); }