From 3f5fdaebb4601623fead0fcdacb8055a5baa1902 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Mon, 15 Sep 2014 13:49:18 -0500 Subject: [PATCH] Add specs for Rex::Encoder::NDR --- spec/lib/rex/encoder/ndr_spec.rb | 169 ++++++++++++++++++ .../examples/rex/encoder/ndr/wstring.rb | 18 ++ .../rex/encoder/ndr/wstring_prebuild.rb | 39 ++++ 3 files changed, 226 insertions(+) create mode 100644 spec/lib/rex/encoder/ndr_spec.rb create mode 100644 spec/support/shared/examples/rex/encoder/ndr/wstring.rb create mode 100644 spec/support/shared/examples/rex/encoder/ndr/wstring_prebuild.rb diff --git a/spec/lib/rex/encoder/ndr_spec.rb b/spec/lib/rex/encoder/ndr_spec.rb new file mode 100644 index 0000000000..57a1f60829 --- /dev/null +++ b/spec/lib/rex/encoder/ndr_spec.rb @@ -0,0 +1,169 @@ +# -*- coding:binary -*- +require 'spec_helper' + +require 'rex/encoder/ndr' + +describe Rex::Encoder::NDR do + + describe ".align" do + subject { described_class.align(string) } + + context "when empty string argument" do + let(:string) { "" } + it { is_expected.to eq("") } + end + + context "when 32bit aligned length argument" do + let(:string) { "A" * 4 } + it { is_expected.to eq("") } + end + + context "when 32bit unaligned length argument" do + let(:string) { "A" * 5 } + it "returns the padding, as null bytes, necessary to 32bit align the argument" do + is_expected.to eq("\x00\x00\x00") + end + end + end + + describe ".long" do + subject { described_class.long(string) } + let(:string) { 0x41424344 } + + it "encodes the arguments as 32-bit little-endian unsigned integer" do + is_expected.to eq("\x44\x43\x42\x41") + end + + context "when argument bigger than 32-bit unsigned integer" do + let(:string) { 0x4142434445 } + it "truncates the argument" do + is_expected.to eq("\x45\x44\x43\x42") + end + end + end + + describe ".short" do + subject { described_class.short(string) } + let(:string) { 0x4142 } + + it "encodes the arguments as 16-bit little-endian unsigned integer" do + is_expected.to eq("\x42\x41") + end + + context "when argument bigger than 16-bit unsigned integer" do + let(:string) { 0x41424344 } + it "truncates the argument" do + is_expected.to eq("\x44\x43") + end + end + + end + + describe ".byte" do + subject { described_class.byte(string) } + let(:string) { 0x41 } + + it "encodes the arguments as 8-bit unsigned integer" do + is_expected.to eq("\x41") + end + + context "when argument bigger than 8-bit unsigned integer" do + let(:string) { 0x4142 } + it "truncates the argument" do + is_expected.to eq("\x42") + end + end + + end + + describe ".UniConformantArray" do + subject { described_class.UniConformantArray(string) } + let(:string) { "ABCDE" } + + it "returns the encoded string" do + is_expected.to be_kind_of(String) + end + + it "starts encoding the string length as 32-bit little-endian unsigned integer" do + expect(subject.unpack("V").first).to eq(string.length) + end + + it "adds the string argument" do + is_expected.to include(string) + end + + it "ends with padding to make result length 32-bits aligned" do + is_expected.to end_with("\x00" * 3) + end + end + + describe ".string" do + subject { described_class.string(string) } + let(:string) { "ABCD" } + + it "returns the encoded string" do + is_expected.to be_kind_of(String) + expect(subject.length).to eq(20) + end + + it "starts encoding string metadata" do + expect(subject.unpack("VVV")[0]).to eq(string.length) + expect(subject.unpack("VVV")[1]).to eq(0) + expect(subject.unpack("VVV")[2]).to eq(string.length) + end + + it "adds the string argument null-byte terminated" do + is_expected.to include("ABCD\x00") + end + + it "ends with padding to make result length 32-bits aligned" do + is_expected.to end_with("\x00" * 3) + end + end + + describe ".wstring" do + subject { described_class.wstring(string) } + + it_behaves_like "Rex::Encoder::NDR.wstring" + end + + describe ".UnicodeConformantVaryingString" do + subject { described_class.UnicodeConformantVaryingString(string) } + + it_behaves_like "Rex::Encoder::NDR.wstring" + end + + describe ".uwstring" do + subject { described_class.uwstring(string) } + + let(:string) { "ABCD" } + + it "encodes the argument as null-terminated unicode string" do + is_expected.to include("A\x00B\x00C\x00D\x00\x00\x00") + end + + it "starts encoding string metadata" do + expect(subject.unpack("VVVV")[1]).to eq(string.length + 1) + expect(subject.unpack("VVVV")[2]).to eq(0) + expect(subject.unpack("VVVV")[3]).to eq(string.length + 1) + end + + it "ends with padding to make result length 32-bits aligned" do + is_expected.to end_with("\x00" * 2) + expect(subject.length).to eq(28) + end + end + + describe ".wstring_prebuilt" do + subject { described_class.wstring_prebuilt(string) } + + it_behaves_like "Rex::Encoder::NDR.wstring_prebuild" + end + + describe ".UnicodeConformantVaryingStringPreBuilt" do + subject { described_class.UnicodeConformantVaryingStringPreBuilt(string) } + + it_behaves_like "Rex::Encoder::NDR.wstring_prebuild" + end + +end diff --git a/spec/support/shared/examples/rex/encoder/ndr/wstring.rb b/spec/support/shared/examples/rex/encoder/ndr/wstring.rb new file mode 100644 index 0000000000..75d79587cb --- /dev/null +++ b/spec/support/shared/examples/rex/encoder/ndr/wstring.rb @@ -0,0 +1,18 @@ +shared_examples_for "Rex::Encoder::NDR.wstring" do + let(:string) { "ABCD" } + + it "encodes the argument as null-terminated unicode string" do + is_expected.to include("A\x00B\x00C\x00D\x00\x00\x00") + end + + it "starts encoding string metadata" do + expect(subject.unpack("VVV")[0]).to eq(string.length + 1) + expect(subject.unpack("VVV")[1]).to eq(0) + expect(subject.unpack("VVV")[2]).to eq(string.length + 1) + end + + it "ends with padding to make result length 32-bits aligned" do + is_expected.to end_with("\x00" * 2) + expect(subject.length).to eq(24) + end +end diff --git a/spec/support/shared/examples/rex/encoder/ndr/wstring_prebuild.rb b/spec/support/shared/examples/rex/encoder/ndr/wstring_prebuild.rb new file mode 100644 index 0000000000..49dc812aba --- /dev/null +++ b/spec/support/shared/examples/rex/encoder/ndr/wstring_prebuild.rb @@ -0,0 +1,39 @@ +shared_examples_for "Rex::Encoder::NDR.wstring_prebuild" do + context "when 2-byte aligned string length" do + let(:string) { "A\x00B\x00C\x00" } + + it "encodes the argument as null-terminated unicode string" do + is_expected.to include("A\x00B\x00C\x00") + end + + it "starts encoding string metadata" do + expect(subject.unpack("VVV")[0]).to eq(string.length / 2) + expect(subject.unpack("VVV")[1]).to eq(0) + expect(subject.unpack("VVV")[2]).to eq(string.length / 2) + end + + it "ends with padding to make result length 32-bits aligned" do + is_expected.to end_with("\x00" * 2) + expect(subject.length).to eq(20) + end + end + + context "when 2-byte unaligned string length" do + let(:string) { "A\x00B\x00C" } + + it "encodes the argument as null-terminated unicode string" do + is_expected.to include("A\x00B\x00C\x00") + end + + it "starts encoding string metadata" do + expect(subject.unpack("VVV")[0]).to eq((string.length + 1) / 2) + expect(subject.unpack("VVV")[1]).to eq(0) + expect(subject.unpack("VVV")[2]).to eq((string.length + 1) / 2) + end + + it "ends with padding to make result length 32-bits aligned" do + is_expected.to end_with("\x00" * 2) + expect(subject.length).to eq(20) + end + end +end \ No newline at end of file