| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "sandbox/src/service_resolver.h" | 5 #include "sandbox/src/service_resolver.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "base/pe_image.h" | 8 #include "base/pe_image.h" |
| 9 #include "base/scoped_ptr.h" | 9 #include "base/scoped_ptr.h" |
| 10 #include "sandbox/src/sandbox_types.h" | 10 #include "sandbox/src/sandbox_types.h" |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 109 bool WriteProtectedChildMemory(HANDLE child_process, | 109 bool WriteProtectedChildMemory(HANDLE child_process, |
| 110 void* address, | 110 void* address, |
| 111 const void* buffer, | 111 const void* buffer, |
| 112 size_t length) { | 112 size_t length) { |
| 113 // first, remove the protections | 113 // first, remove the protections |
| 114 DWORD old_protection; | 114 DWORD old_protection; |
| 115 if (!::VirtualProtectEx(child_process, address, length, | 115 if (!::VirtualProtectEx(child_process, address, length, |
| 116 PAGE_WRITECOPY, &old_protection)) | 116 PAGE_WRITECOPY, &old_protection)) |
| 117 return false; | 117 return false; |
| 118 | 118 |
| 119 DWORD written; | 119 SIZE_T written; |
| 120 bool ok = ::WriteProcessMemory(child_process, address, buffer, length, | 120 bool ok = ::WriteProcessMemory(child_process, address, buffer, length, |
| 121 &written) && (length == written); | 121 &written) && (length == written); |
| 122 | 122 |
| 123 // always attempt to restore the original protection | 123 // always attempt to restore the original protection |
| 124 if (!::VirtualProtectEx(child_process, address, length, | 124 if (!::VirtualProtectEx(child_process, address, length, |
| 125 old_protection, &old_protection)) | 125 old_protection, &old_protection)) |
| 126 return false; | 126 return false; |
| 127 | 127 |
| 128 return ok; | 128 return ok; |
| 129 } | 129 } |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 190 | 190 |
| 191 return STATUS_SUCCESS; | 191 return STATUS_SUCCESS; |
| 192 } | 192 } |
| 193 | 193 |
| 194 size_t ServiceResolverThunk::GetThunkSize() const { | 194 size_t ServiceResolverThunk::GetThunkSize() const { |
| 195 return offsetof(ServiceFullThunk, internal_thunk) + GetInternalThunkSize(); | 195 return offsetof(ServiceFullThunk, internal_thunk) + GetInternalThunkSize(); |
| 196 } | 196 } |
| 197 | 197 |
| 198 bool ServiceResolverThunk::IsFunctionAService(void* local_thunk) const { | 198 bool ServiceResolverThunk::IsFunctionAService(void* local_thunk) const { |
| 199 ServiceEntry function_code; | 199 ServiceEntry function_code; |
| 200 DWORD read; | 200 SIZE_T read; |
| 201 if (!::ReadProcessMemory(process_, target_, &function_code, | 201 if (!::ReadProcessMemory(process_, target_, &function_code, |
| 202 sizeof(function_code), &read)) | 202 sizeof(function_code), &read)) |
| 203 return false; | 203 return false; |
| 204 | 204 |
| 205 if (sizeof(function_code) != read) | 205 if (sizeof(function_code) != read) |
| 206 return false; | 206 return false; |
| 207 | 207 |
| 208 if (kMovEax != function_code.mov_eax || | 208 if (kMovEax != function_code.mov_eax || |
| 209 kMovEdx != function_code.mov_edx || | 209 kMovEdx != function_code.mov_edx || |
| 210 (kCallPtrEdx != function_code.call_ptr_edx && | 210 (kCallPtrEdx != function_code.call_ptr_edx && |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 286 bytes_to_write = offsetof(ServiceEntry, mov_edx); | 286 bytes_to_write = offsetof(ServiceEntry, mov_edx); |
| 287 } | 287 } |
| 288 | 288 |
| 289 // setup the thunk | 289 // setup the thunk |
| 290 SetInternalThunk(&full_local_thunk->internal_thunk, GetInternalThunkSize(), | 290 SetInternalThunk(&full_local_thunk->internal_thunk, GetInternalThunkSize(), |
| 291 remote_thunk, interceptor_); | 291 remote_thunk, interceptor_); |
| 292 | 292 |
| 293 size_t thunk_size = GetThunkSize(); | 293 size_t thunk_size = GetThunkSize(); |
| 294 | 294 |
| 295 // copy the local thunk buffer to the child | 295 // copy the local thunk buffer to the child |
| 296 DWORD written; | 296 SIZE_T written; |
| 297 if (!::WriteProcessMemory(process_, remote_thunk, local_thunk, | 297 if (!::WriteProcessMemory(process_, remote_thunk, local_thunk, |
| 298 thunk_size, &written)) | 298 thunk_size, &written)) |
| 299 return STATUS_UNSUCCESSFUL; | 299 return STATUS_UNSUCCESSFUL; |
| 300 | 300 |
| 301 if (thunk_size != written) | 301 if (thunk_size != written) |
| 302 return STATUS_UNSUCCESSFUL; | 302 return STATUS_UNSUCCESSFUL; |
| 303 | 303 |
| 304 // and now change the function to intercept, on the child | 304 // and now change the function to intercept, on the child |
| 305 if (NULL != ntdll_base_) { | 305 if (NULL != ntdll_base_) { |
| 306 // running a unit test | 306 // running a unit test |
| 307 if (!::WriteProcessMemory(process_, target_, &intercepted_code, | 307 if (!::WriteProcessMemory(process_, target_, &intercepted_code, |
| 308 bytes_to_write, &written)) | 308 bytes_to_write, &written)) |
| 309 return STATUS_UNSUCCESSFUL; | 309 return STATUS_UNSUCCESSFUL; |
| 310 } else { | 310 } else { |
| 311 if (!::WriteProtectedChildMemory(process_, target_, &intercepted_code, | 311 if (!::WriteProtectedChildMemory(process_, target_, &intercepted_code, |
| 312 bytes_to_write)) | 312 bytes_to_write)) |
| 313 return STATUS_UNSUCCESSFUL; | 313 return STATUS_UNSUCCESSFUL; |
| 314 } | 314 } |
| 315 | 315 |
| 316 return STATUS_SUCCESS; | 316 return STATUS_SUCCESS; |
| 317 } | 317 } |
| 318 | 318 |
| 319 bool ServiceResolverThunk::SaveOriginalFunction(void* local_thunk, | 319 bool ServiceResolverThunk::SaveOriginalFunction(void* local_thunk, |
| 320 void* remote_thunk) { | 320 void* remote_thunk) { |
| 321 ServiceEntry function_code; | 321 ServiceEntry function_code; |
| 322 DWORD read; | 322 SIZE_T read; |
| 323 if (!::ReadProcessMemory(process_, target_, &function_code, | 323 if (!::ReadProcessMemory(process_, target_, &function_code, |
| 324 sizeof(function_code), &read)) | 324 sizeof(function_code), &read)) |
| 325 return false; | 325 return false; |
| 326 | 326 |
| 327 if (sizeof(function_code) != read) | 327 if (sizeof(function_code) != read) |
| 328 return false; | 328 return false; |
| 329 | 329 |
| 330 if (kJmp32 == function_code.mov_eax) { | 330 if (kJmp32 == function_code.mov_eax) { |
| 331 // Plain old entry point patch. The relative jump address follows it. | 331 // Plain old entry point patch. The relative jump address follows it. |
| 332 ULONG relative = function_code.service_id; | 332 ULONG relative = function_code.service_id; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 347 } | 347 } |
| 348 | 348 |
| 349 // Save the verified code | 349 // Save the verified code |
| 350 memcpy(local_thunk, &function_code, sizeof(function_code)); | 350 memcpy(local_thunk, &function_code, sizeof(function_code)); |
| 351 | 351 |
| 352 return true; | 352 return true; |
| 353 } | 353 } |
| 354 | 354 |
| 355 bool Wow64ResolverThunk::IsFunctionAService(void* local_thunk) const { | 355 bool Wow64ResolverThunk::IsFunctionAService(void* local_thunk) const { |
| 356 Wow64Entry function_code; | 356 Wow64Entry function_code; |
| 357 DWORD read; | 357 SIZE_T read; |
| 358 if (!::ReadProcessMemory(process_, target_, &function_code, | 358 if (!::ReadProcessMemory(process_, target_, &function_code, |
| 359 sizeof(function_code), &read)) | 359 sizeof(function_code), &read)) |
| 360 return false; | 360 return false; |
| 361 | 361 |
| 362 if (sizeof(function_code) != read) | 362 if (sizeof(function_code) != read) |
| 363 return false; | 363 return false; |
| 364 | 364 |
| 365 if (kMovEax != function_code.mov_eax || kXorEcx != function_code.xor_ecx || | 365 if (kMovEax != function_code.mov_eax || kXorEcx != function_code.xor_ecx || |
| 366 kLeaEdx != function_code.lea_edx || kCallFs1 != function_code.call_fs1 || | 366 kLeaEdx != function_code.lea_edx || kCallFs1 != function_code.call_fs1 || |
| 367 kCallFs2 != function_code.call_fs2 || kCallFs3 != function_code.call_fs3) | 367 kCallFs2 != function_code.call_fs2 || kCallFs3 != function_code.call_fs3) |
| 368 return false; | 368 return false; |
| 369 | 369 |
| 370 if ((kAddEsp1 == function_code.add_esp1 && | 370 if ((kAddEsp1 == function_code.add_esp1 && |
| 371 kAddEsp2 == function_code.add_esp2 && | 371 kAddEsp2 == function_code.add_esp2 && |
| 372 kRet == function_code.ret) || kRet == function_code.add_esp1) { | 372 kRet == function_code.ret) || kRet == function_code.add_esp1) { |
| 373 // Save the verified code | 373 // Save the verified code |
| 374 memcpy(local_thunk, &function_code, sizeof(function_code)); | 374 memcpy(local_thunk, &function_code, sizeof(function_code)); |
| 375 return true; | 375 return true; |
| 376 } | 376 } |
| 377 | 377 |
| 378 return false; | 378 return false; |
| 379 } | 379 } |
| 380 | 380 |
| 381 bool Win2kResolverThunk::IsFunctionAService(void* local_thunk) const { | 381 bool Win2kResolverThunk::IsFunctionAService(void* local_thunk) const { |
| 382 ServiceEntry function_code; | 382 ServiceEntry function_code; |
| 383 DWORD read; | 383 SIZE_T read; |
| 384 if (!::ReadProcessMemory(process_, target_, &function_code, | 384 if (!::ReadProcessMemory(process_, target_, &function_code, |
| 385 sizeof(function_code), &read)) | 385 sizeof(function_code), &read)) |
| 386 return false; | 386 return false; |
| 387 | 387 |
| 388 if (sizeof(function_code) != read) | 388 if (sizeof(function_code) != read) |
| 389 return false; | 389 return false; |
| 390 | 390 |
| 391 if (kMovEax != function_code.mov_eax || | 391 if (kMovEax != function_code.mov_eax || |
| 392 function_code.service_id > kMaxService) | 392 function_code.service_id > kMaxService) |
| 393 return false; | 393 return false; |
| 394 | 394 |
| 395 // Save the verified code | 395 // Save the verified code |
| 396 memcpy(local_thunk, &function_code, sizeof(function_code)); | 396 memcpy(local_thunk, &function_code, sizeof(function_code)); |
| 397 | 397 |
| 398 return true; | 398 return true; |
| 399 } | 399 } |
| 400 | 400 |
| 401 } // namespace sandbox | 401 } // namespace sandbox |
| OLD | NEW |