2010-08-26 40 views
11

Máy chủ của một người bạn (có, thực sự. Không phải của tôi.) Đã được chia thành và chúng tôi phát hiện một mã nhị phân perl chạy một số mã bot. Chúng tôi không thể tìm thấy chính kịch bản (có thể được đánh giá là đã nhận được qua mạng), nhưng chúng tôi đã tạo ra một kết xuất lõi của quy trình perl.Kỹ thuật đảo ngược một kịch bản Perl dựa trên một khối lõi

Chuỗi chạy trên lõi đã cho chúng tôi một số gợi ý (tên máy chủ, tên người dùng/mật khẩu), nhưng không phải là mã nguồn của tập lệnh.

Chúng tôi muốn biết kịch bản có khả năng làm gì, vì vậy chúng tôi muốn đảo ngược kỹ thuật mã perl đang chạy bên trong trình thông dịch perl đó.

Tìm kiếm xung quanh, thứ gần nhất với trình biên dịch perl mà tôi tìm thấy là mô đun B :: Deparse có vẻ hoàn toàn phù hợp để chuyển đổi bytecode của phân tích cú pháp thành mã có thể đọc được.

Bây giờ, làm cách nào để B :: Deparse hoạt động trên một bãi chứa lõi? Hoặc, cách khác, làm thế nào tôi có thể khởi động lại chương trình từ lõi, tải B :: Deparse và thực hiện nó?

Mọi ý tưởng đều được chào đón.

Trả lời

7

ysth đã yêu cầu tôi về IRC để nhận xét về câu hỏi của bạn. Tôi đã thực hiện toàn bộ đống công cụ "tháo" perl được biên dịch và nội dung (chỉ cần xem trang CPAN của mình [http://search.cpan.org/~jjore]).

Perl biên dịch nguồn của bạn thành một cây có kích thướccấu trúc mà thỉnh thoảng có C con trỏ tới SV* là giá trị perl. Hiện tại, phân đoạn cốt lõi của bạn đã bị xóa một trong số các mã OP*SV* được lưu trữ.

Thế giới tốt nhất có thể là có mô-đun perl như B::Deparse thực hiện công việc thông tin cho bạn. Nó hoạt động bằng cách sử dụng giao diện ánh sáng cho bộ nhớ perl trong các lớp B::OPB::SV (được ghi trong B, perlgutsperlhack).Điều này là không thực tế đối với bạn bởi vì một đối tượng B::* là chỉ là một con trỏ vào bộ nhớ với các trình truy cập để giải mã cấu trúc cho việc sử dụng của chúng tôi. Xem xét:

require Data::Dumper; 
require Scalar::Util; 
require B; 

my $value = 'this is a string'; 

my $sv  = B::svref_2object(\ $value); 
my $address = Scalar::Util::refaddr(\ $value); 

local $Data::Dumper::Sortkeys = 1; 
local $Data::Dumper::Purity = 1; 
print Data::Dumper::Dumper(
    { 
    address => $address, 
    value => \ $value, 
    sv  => $sv, 
    sv_attr => { 
     CUR   => $sv->CUR, 
     LEN   => $sv->LEN, 
     PV   => $sv->PV, 
     PVBM   => $sv->PVBM, 
     PVX   => $sv->PVX, 
     as_string  => $sv->as_string, 
     FLAGS   => $sv->FLAGS, 
     MAGICAL  => $sv->MAGICAL, 
     POK   => $sv->POK, 
     REFCNT  => $sv->REFCNT, 
     ROK   => $sv->ROK, 
     SvTYPE  => $sv->SvTYPE, 
     object_2svref => $sv->object_2svref, 
    }, 
    } 
); 

mà khi chạy cho thấy rằng đối tượng B::PV (nó là ISA B::SV) là thật sự chỉ đơn thuần là một giao diện để các đại diện bộ nhớ của chuỗi biên soạn this is a string.

$VAR1 = { 
      'address' => 438506984, 
      'sv' => bless(do{\(my $o = 438506984)}, 'B::PV'), 
      'sv_attr' => { 
         'CUR' => 16, 
         'FLAGS' => 279557, 
         'LEN' => 24, 
         'MAGICAL' => 0, 
         'POK' => 1024, 
         'PV' => 'this is a string', 
         'PVBM' => 'this is a string', 
         'PVX' => 'this is a string', 
         'REFCNT' => 2, 
         'ROK' => 0, 
         'SvTYPE' => 5, 
         'as_string' => 'this is a string', 
         'object_2svref' => \'this is a string' 
         }, 
      'value' => do{my $o} 
     }; 
$VAR1->{'value'} = $VAR1->{'sv_attr'}{'object_2svref'}; 

Tuy nhiên điều này có nghĩa là bất kỳ B::* sử dụng mã thực sự phải hoạt động vào bộ nhớ trực tiếp. Tye McQueen nghĩ rằng ông nhớ một trình gỡ lỗi C mà hoàn toàn có thể làm sống lại một quá trình làm việc được đưa ra một bãi chứa lõi. My gdb không thể. gdb có thể cho phép bạn đổ nội dung của các cấu trúc OP*SV* của bạn. Bạn rất có thể sẽ chỉ đọc các cấu trúc đã bị bán phá giá để diễn giải cấu trúc chương trình của bạn. Nếu bạn muốn, hãy sử dụng gdb để đổ các cấu trúc, sau đó tổng hợp các đối tượng B::* đối tượng hoạt động trong giao diện giống như chúng bình thường và sử dụng B::Deparse trên đó. Tại gốc, deparser của chúng tôi và gỡ lỗi khác bán phá giá công cụ chủ yếu là đối tượng theo định hướng để bạn chỉ có thể "đánh lừa" chúng bằng cách tạo ra một đống giả B::* lớp học và các đối tượng.

Bạn có thể đọc phương thức coderef2text của B :: Deparse lớp hướng dẫn. Nó chấp nhận một tham chiếu chức năng, phôi nó vào một đối tượng B::CV , và sử dụng nó để đầu vào cho các phương pháp deparse_sub:

require B; 
require B::Deparse; 
sub your_function { ... } 

my $cv = B::svref_2object(\ &your_function); 
my $deparser = B::Deparse->new; 
print $deparser->deparse_sub($cv); 

Đối với lời giới thiệu nhẹ nhàng để OP* và ý tưởng liên quan, vui lòng xem cập nhật PerlGuts IllustratedOptree guts.

+0

Josh, cảm ơn câu trả lời chi tiết. Điều này khá nhiều người vợ với những gì tôi mong đợi. Trông giống như một dự án cho những đêm mùa đông dài. – otmar

0

Vâng, undump sẽ biến phân đoạn cốt lõi đó trở lại thành tệp thực thi nhị phân (nếu bạn có thể tìm thấy phiên bản hoạt động). Sau đó, bạn có thể tải nội dung đó vào số perl-MO=Deparse.

+2

Err, tôi nghĩ có một lỗ hổng ở đó; làm thế nào để bạn tải một tập tin nhị phân thực thi vào perl? – ysth

+0

Tôi đã có ấn tượng rằng tôi vừa mới thực hiện 'perl a.out' một trong những ngày sau đây theo hướng dẫn Par :: Packer, nhưng tôi đã thử nó ngay bây giờ và nó không hoạt động. –

2

tôi nghi ngờ có một công cụ ra khỏi đó mà thực hiện điều này ra khỏi hộp, vì vậy ...

  1. Tìm mã nguồn để các phiên bản của perl bạn đang chạy. Điều này sẽ giúp bạn hiểu cách bố trí bộ nhớ của trình thông dịch perl. Nó cũng sẽ giúp bạn tìm ra nếu có một cách để có một phím tắt ở đây (ví dụ: nếu bytecode được bắt đầu bởi một tiêu đề dễ tìm trong bộ nhớ hoặc một cái gì đó).

  2. tải lên nhị phân bãi + cốt lõi trong một trình gỡ lỗi, có lẽ gdb

  3. Sử dụng thông tin trong mã nguồn perl để hướng dẫn bạn trong việc thuyết phục các debugger để nhổ ra bytecode bạn quan tâm.

Khi bạn có bytecode, B :: Deparse sẽ có thể đưa bạn đến nội dung dễ đọc hơn.

+0

Có, điều đó nghe có vẻ hợp lý. Có thể có một bắt, mặc dù: Tài liệu perl đề cập đến mã byte như phân tích-cây. Điều này cho thấy rằng mã byte không phải là một mảng các mã op độc lập với địa chỉ của nó trong bộ nhớ. Thay vào đó, âm thanh này giống như một số loại cây với con trỏ và thậm chí có thể là con trỏ tới mã thực thi nguyên thủy. Vì vậy, tôi không chắc chắn liệu B :: Deparse có thể đối phó với một cây phân tích được tạo ra bởi một cá thể perl khác. – otmar

+0

Nhìn vào mã Deparse cho thấy một vấn đề khác: Deparse oeprated trên các đối tượng perl đại diện cho chương trình, và không phải là bộ nhớ/byte-luồng lưu trữ mã đó. – otmar

Các vấn đề liên quan