Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(839)

Side by Side Diff: tools/goopdump/process_commandline.cc

Issue 624713003: Keep only base/extractor.[cc|h]. (Closed) Base URL: https://chromium.googlesource.com/external/omaha.git@master
Patch Set: Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « tools/goopdump/process_commandline.h ('k') | tools/goopdump/process_commandline_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2008-2009 Google Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 // ========================================================================
15
16 #include "omaha/tools/goopdump/process_commandline.h"
17
18 #include "omaha/common/debug.h"
19 #include "omaha/common/error.h"
20 #include "omaha/common/scoped_any.h"
21 #include "omaha/common/utils.h"
22
23 namespace omaha {
24
25 namespace {
26
27 typedef const wchar_t* (__stdcall *GetCommandLineWFunc)();
28
29 const DWORD kMaxInjectSize = 4096;
30 const DWORD kCmdLineBufferSize = 2000;
31
32 struct SharedBlock {
33 DWORD last_error; // Last error from remote thread.
34 GetCommandLineWFunc get_commandline_w_ptr; // Address of GetCommandLineW().
35 wchar_t cmd_line_buffer[kCmdLineBufferSize]; // The command line buffer.
36 };
37
38 // A number of assumptions are made:
39 // * The target process is a Win32 process.
40 // * Kernel32.dll is loaded at same address in each process (safe).
41 // * InjectFunction() is shorter than kMaxInjectSize
42 // * InjectFunction() does not rely on the C/C++ runtime.
43 // * Compiler option /GZ is not used. (If it is, the compiler generates calls to
44 // functions which are not injected into the target. The runtime_checks()
45 // pragma below removes this for debug builds which will have /GZ enabled by
46 // default.
47
48 #pragma runtime_checks("", off)
49
50 DWORD __stdcall InjectFunction(SharedBlock* shared_block) {
51 const wchar_t* source = shared_block->get_commandline_w_ptr();
52 wchar_t* target = &shared_block->cmd_line_buffer[0];
53 wchar_t* end = &shared_block->cmd_line_buffer[
54 arraysize(shared_block->cmd_line_buffer) - 1];
55 if (source == 0 || target == 0 || end == 0) {
56 shared_block->last_error = ERROR_INVALID_DATA;
57 return 0;
58 }
59
60 // This is effectively a wcscpy but we can't use library functions since this
61 // code will be injected into the target process space and we can't make
62 // assumptions about what's linked into that process.
63 for (; *source != 0 && target < end; ++source, ++target) {
64 *target = *source;
65 }
66
67 *target = 0;
68 shared_block->last_error = 0;
69
70 return 0;
71 }
72
73 #pragma runtime_checks("", restore)
74
75 // Internal helper function to deal with the logic of injecting the
76 // function/data into the process without the memory alloc/free since we don't
77 // have smart pointers to handle VirtualAllocEx.
78 HRESULT GetCommandLineFromHandleWithMemory(HANDLE process_handle,
79 void* function_memory,
80 SharedBlock* shared_block,
81 CString* command_line) {
82 ASSERT1(process_handle);
83 ASSERT1(function_memory);
84 ASSERT1(shared_block);
85
86 // Copy function into other process.
87 if (!::WriteProcessMemory(process_handle,
88 function_memory,
89 &InjectFunction,
90 kMaxInjectSize,
91 0)) {
92 return HRESULTFromLastError();
93 }
94
95 // Initialize data area for remote process.
96 scoped_library hmodule_kernel32(::LoadLibrary(L"kernel32.dll"));
97 if (!hmodule_kernel32) {
98 return HRESULTFromLastError();
99 }
100
101 SharedBlock shared_block_local;
102 shared_block_local.last_error = 0;
103 if (!GPA(get(hmodule_kernel32),
104 "GetCommandLineW",
105 &shared_block_local.get_commandline_w_ptr)) {
106 return HRESULTFromLastError();
107 }
108
109 shared_block_local.cmd_line_buffer[0] = L'\0';
110
111 if (!::WriteProcessMemory(process_handle,
112 shared_block,
113 &shared_block_local,
114 sizeof(shared_block_local),
115 0)) {
116 return HRESULTFromLastError();
117 }
118
119 // Create the remote thread.
120 scoped_handle remote_thread;
121 reset(remote_thread, ::CreateRemoteThread(
122 process_handle,
123 0,
124 0,
125 reinterpret_cast<LPTHREAD_START_ROUTINE>(function_memory),
126 shared_block,
127 0,
128 NULL));
129 if (!remote_thread) {
130 return HRESULTFromLastError();
131 }
132
133 const DWORD kWaitTimeoutMs = 3000;
134 DWORD wait_result = ::WaitForSingleObject(get(remote_thread), kWaitTimeoutMs);
135 switch (wait_result) {
136 case WAIT_TIMEOUT:
137 return HRESULT_FROM_WIN32(ERROR_TIMEOUT);
138 case WAIT_FAILED:
139 return HRESULTFromLastError();
140 case WAIT_OBJECT_0:
141 // This might just have worked, pick up the result.
142 if (!::ReadProcessMemory(process_handle,
143 shared_block,
144 &shared_block_local,
145 sizeof(shared_block_local),
146 0)) {
147 return HRESULTFromLastError();
148 }
149 if (shared_block_local.last_error == 0) {
150 *command_line = shared_block_local.cmd_line_buffer;
151 } else {
152 return HRESULT_FROM_WIN32(shared_block_local.last_error);
153 }
154 break;
155 default:
156 return HRESULTFromLastError();
157 }
158
159 return S_OK;
160 }
161
162 // Allocates memory in a remote process given the process handle.
163 // Returns a block of memory for the function that will be injected and a block
164 // of memory to store results in that we copy back out.
165 HRESULT AllocateProcessMemory(HANDLE process_handle,
166 void** function_memory,
167 void** shared_block) {
168 ASSERT1(process_handle);
169 ASSERT1(function_memory);
170 ASSERT1(shared_block);
171
172 *function_memory = ::VirtualAllocEx(process_handle,
173 0,
174 kMaxInjectSize,
175 MEM_COMMIT,
176 PAGE_EXECUTE_READWRITE);
177 if (!(*function_memory)) {
178 return HRESULTFromLastError();
179 }
180
181 *shared_block = ::VirtualAllocEx(process_handle,
182 0,
183 sizeof(SharedBlock),
184 MEM_COMMIT,
185 PAGE_READWRITE);
186 if (!(*shared_block)) {
187 ::VirtualFreeEx(process_handle, *function_memory, 0, MEM_RELEASE);
188 *function_memory = NULL;
189 return HRESULTFromLastError();
190 }
191
192 return S_OK;
193 }
194
195 HRESULT GetCommandLineFromHandle(HANDLE process_handle, CString* command_line) {
196 ASSERT1(command_line);
197 ASSERT1(process_handle != NULL);
198
199 void* function_memory = NULL;
200 void* shared_block = NULL;
201
202 HRESULT hr = AllocateProcessMemory(process_handle,
203 &function_memory,
204 &shared_block);
205
206 if (SUCCEEDED(hr) && function_memory && shared_block) {
207 hr = GetCommandLineFromHandleWithMemory(
208 process_handle,
209 function_memory,
210 reinterpret_cast<SharedBlock*>(shared_block),
211 command_line);
212 }
213
214 if (function_memory) {
215 ::VirtualFreeEx(process_handle, function_memory, 0, MEM_RELEASE);
216 function_memory = NULL;
217 }
218
219 if (shared_block) {
220 ::VirtualFreeEx(process_handle, shared_block, 0, MEM_RELEASE);
221 shared_block = NULL;
222 }
223
224 return hr;
225 }
226
227 } // namespace
228
229 HRESULT GetProcessCommandLine(DWORD process_id, CString* command_line) {
230 ASSERT1(command_line);
231
232 EnableDebugPrivilege();
233 scoped_handle process_handle;
234 reset(process_handle, ::OpenProcess(PROCESS_CREATE_THREAD |
235 PROCESS_VM_OPERATION |
236 PROCESS_VM_WRITE |
237 PROCESS_VM_READ,
238 FALSE,
239 process_id));
240 if (!valid(process_handle)) {
241 return HRESULTFromLastError();
242 }
243 return GetCommandLineFromHandle(get(process_handle), command_line);
244 }
245
246 bool EnableDebugPrivilege() {
247 scoped_handle token;
248
249 if (!::OpenProcessToken(::GetCurrentProcess(),
250 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
251 address(token))) {
252 return false;
253 }
254
255 LUID se_debug_name_value = {0};
256 if (!::LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &se_debug_name_value)) {
257 return false;
258 }
259
260 TOKEN_PRIVILEGES token_privs = {0};
261 token_privs.PrivilegeCount = 1;
262 token_privs.Privileges[0].Luid = se_debug_name_value;
263 token_privs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
264
265 if (!::AdjustTokenPrivileges(get(token),
266 FALSE,
267 &token_privs,
268 sizeof(token_privs),
269 NULL,
270 NULL)) {
271 return false;
272 }
273
274 return true;
275 }
276
277 } // namespace omaha
278
OLDNEW
« no previous file with comments | « tools/goopdump/process_commandline.h ('k') | tools/goopdump/process_commandline_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698