... | ... |
@@ -115,6 +115,11 @@ static void tracehook_val(struct cli_bc_ctx *ctx, const char *name, uint32_t val |
115 | 115 |
fprintf(stderr, "[trace] %s = %u\n", name, value); |
116 | 116 |
} |
117 | 117 |
|
118 |
+static void tracehook_ptr(struct cli_bc_ctx *ctx, const void *ptr) |
|
119 |
+{ |
|
120 |
+ fprintf(stderr, "[trace] %p\n", ptr); |
|
121 |
+} |
|
122 |
+ |
|
118 | 123 |
int main(int argc, char *argv[]) |
119 | 124 |
{ |
120 | 125 |
FILE *f; |
... | ... |
@@ -219,7 +224,8 @@ int main(int argc, char *argv[]) |
219 | 219 |
cli_bytecode_context_set_trace(ctx, tracelevel, |
220 | 220 |
tracehook, |
221 | 221 |
tracehook_op, |
222 |
- tracehook_val); |
|
222 |
+ tracehook_val, |
|
223 |
+ tracehook_ptr); |
|
223 | 224 |
|
224 | 225 |
if (opts->filename[1]) { |
225 | 226 |
funcid = atoi(opts->filename[1]); |
... | ... |
@@ -57,6 +57,7 @@ struct cli_bc_ctx *cli_bytecode_context_alloc(void) |
57 | 57 |
ctx->trace = NULL; |
58 | 58 |
ctx->trace_op = NULL; |
59 | 59 |
ctx->trace_val = NULL; |
60 |
+ ctx->trace_ptr = NULL; |
|
60 | 61 |
ctx->scope = NULL; |
61 | 62 |
ctx->scopeid = 0; |
62 | 63 |
ctx->file = "??"; |
... | ... |
@@ -1048,7 +1049,7 @@ static int parseBB(struct cli_bc *bc, unsigned func, unsigned bb, unsigned char |
1048 | 1048 |
inst.u.ops.ops = cli_calloc(numOp, sizeof(*inst.u.ops.ops)); |
1049 | 1049 |
if (!inst.u.ops.ops) { |
1050 | 1050 |
cli_errmsg("Out of memory allocating operands\n"); |
1051 |
- return CL_EMALFDB; |
|
1051 |
+ return CL_EMEM; |
|
1052 | 1052 |
} |
1053 | 1053 |
if (inst.opcode == OP_BC_CALL_DIRECT) |
1054 | 1054 |
inst.u.ops.funcid = readFuncID(bc, buffer, &offset, len, &ok); |
... | ... |
@@ -1080,6 +1081,21 @@ static int parseBB(struct cli_bc *bc, unsigned func, unsigned bb, unsigned char |
1080 | 1080 |
(1ull<<inst.u.cast.mask)-1 : |
1081 | 1081 |
~0ull; |
1082 | 1082 |
break; |
1083 |
+ case OP_BC_GEPN: |
|
1084 |
+ numOp = readFixedNumber(buffer, &offset, len, &ok, 1); |
|
1085 |
+ if (ok) { |
|
1086 |
+ inst.u.ops.numOps = numOp+1; |
|
1087 |
+ inst.u.ops.opsizes = NULL; |
|
1088 |
+ inst.u.ops.ops = cli_calloc(numOp, sizeof(*inst.u.ops.ops)); |
|
1089 |
+ if (!inst.u.ops.ops) { |
|
1090 |
+ cli_errmsg("Out of memory allocating operands\n"); |
|
1091 |
+ return CL_EMEM; |
|
1092 |
+ } |
|
1093 |
+ inst.u.ops.ops[0] = readNumber(buffer, &offset, len, &ok); |
|
1094 |
+ for (i=1;i<numOp+1;i++) |
|
1095 |
+ inst.u.ops.ops[i] = readOperand(bcfunc, buffer, &offset, len, &ok); |
|
1096 |
+ } |
|
1097 |
+ break; |
|
1083 | 1098 |
case OP_BC_ICMP_EQ: |
1084 | 1099 |
case OP_BC_ICMP_NE: |
1085 | 1100 |
case OP_BC_ICMP_UGT: |
... | ... |
@@ -1532,14 +1548,13 @@ static int cli_bytecode_prepare_interpreter(struct cli_bc *bc) |
1532 | 1532 |
MAP(inst->u.unaryop); |
1533 | 1533 |
break; |
1534 | 1534 |
case OP_BC_GEP1: |
1535 |
- MAP(inst->u.binop[0]); |
|
1536 |
- MAP(inst->u.binop[1]); |
|
1537 |
- break; |
|
1538 |
- case OP_BC_GEP2: |
|
1539 |
- MAP(inst->u.three[0]); |
|
1535 |
+ //three[0] is the type |
|
1540 | 1536 |
MAP(inst->u.three[1]); |
1541 | 1537 |
MAP(inst->u.three[2]); |
1542 | 1538 |
break; |
1539 |
+ case OP_BC_GEPN: |
|
1540 |
+ /*TODO */ |
|
1541 |
+ break; |
|
1543 | 1542 |
default: |
1544 | 1543 |
cli_dbgmsg("Unhandled opcode: %d\n", inst->opcode); |
1545 | 1544 |
return CL_EBYTECODE; |
... | ... |
@@ -122,10 +122,12 @@ void cli_bytecode_debug_printsrc(const struct cli_bc_ctx *ctx); |
122 | 122 |
typedef void (*bc_dbg_callback_trace)(struct cli_bc_ctx*, unsigned event); |
123 | 123 |
typedef void (*bc_dbg_callback_trace_op)(struct cli_bc_ctx*, const char *op); |
124 | 124 |
typedef void (*bc_dbg_callback_trace_val)(struct cli_bc_ctx*, const char *name, uint32_t value); |
125 |
+typedef void (*bc_dbg_callback_trace_ptr)(struct cli_bc_ctx*, const void *val); |
|
125 | 126 |
void cli_bytecode_context_set_trace(struct cli_bc_ctx*, unsigned level, |
126 | 127 |
bc_dbg_callback_trace, |
127 | 128 |
bc_dbg_callback_trace_op, |
128 |
- bc_dbg_callback_trace_val); |
|
129 |
+ bc_dbg_callback_trace_val, |
|
130 |
+ bc_dbg_callback_trace_ptr); |
|
129 | 131 |
|
130 | 132 |
#ifdef __cplusplus |
131 | 133 |
} |
... | ... |
@@ -142,11 +142,13 @@ int32_t cli_bcapi_write(struct cli_bc_ctx *ctx, uint8_t*data, int32_t len) |
142 | 142 |
void cli_bytecode_context_set_trace(struct cli_bc_ctx* ctx, unsigned level, |
143 | 143 |
bc_dbg_callback_trace trace, |
144 | 144 |
bc_dbg_callback_trace_op trace_op, |
145 |
- bc_dbg_callback_trace_val trace_val) |
|
145 |
+ bc_dbg_callback_trace_val trace_val, |
|
146 |
+ bc_dbg_callback_trace_ptr trace_ptr) |
|
146 | 147 |
{ |
147 | 148 |
ctx->trace = trace; |
148 | 149 |
ctx->trace_op = trace_op; |
149 | 150 |
ctx->trace_val = trace_val; |
151 |
+ ctx->trace_ptr = trace_ptr; |
|
150 | 152 |
ctx->trace_level = level; |
151 | 153 |
} |
152 | 154 |
|
... | ... |
@@ -223,3 +225,17 @@ uint32_t cli_bcapi_trace_value(struct cli_bc_ctx *ctx, const const uint8_t* name |
223 | 223 |
ctx->trace_val(ctx, name, value); |
224 | 224 |
return 0; |
225 | 225 |
} |
226 |
+ |
|
227 |
+uint32_t cli_bcapi_trace_ptr(struct cli_bc_ctx *ctx, const const uint8_t* ptr, uint32_t dummy) |
|
228 |
+{ |
|
229 |
+ if (LIKELY(ctx->trace_level < trace_val)) |
|
230 |
+ return 0; |
|
231 |
+ if (ctx->trace_level&0x80) { |
|
232 |
+ if ((ctx->trace_level&0x7f) < trace_param) |
|
233 |
+ return 0; |
|
234 |
+ ctx->trace(ctx, trace_param); |
|
235 |
+ } |
|
236 |
+ if (ctx->trace_ptr) |
|
237 |
+ ctx->trace_ptr(ctx, ptr); |
|
238 |
+ return 0; |
|
239 |
+} |
... | ... |
@@ -164,6 +164,7 @@ uint32_t trace_scope(const uint8_t* newscope, uint32_t scopeid); |
164 | 164 |
uint32_t trace_source(const uint8_t* srcfile, uint32_t line); |
165 | 165 |
uint32_t trace_op(const uint8_t* opname, uint32_t column); |
166 | 166 |
uint32_t trace_value(const uint8_t* name, uint32_t v); |
167 |
+uint32_t trace_ptr(const uint8_t* ptr, uint32_t dummy); |
|
167 | 168 |
|
168 | 169 |
#endif |
169 | 170 |
#endif |
... | ... |
@@ -47,6 +47,7 @@ uint32_t cli_bcapi_trace_scope(struct cli_bc_ctx *ctx, const const uint8_t*, uin |
47 | 47 |
uint32_t cli_bcapi_trace_source(struct cli_bc_ctx *ctx, const const uint8_t*, uint32_t); |
48 | 48 |
uint32_t cli_bcapi_trace_op(struct cli_bc_ctx *ctx, const const uint8_t*, uint32_t); |
49 | 49 |
uint32_t cli_bcapi_trace_value(struct cli_bc_ctx *ctx, const const uint8_t*, uint32_t); |
50 |
+uint32_t cli_bcapi_trace_ptr(struct cli_bc_ctx *ctx, const const uint8_t*, uint32_t); |
|
50 | 51 |
|
51 | 52 |
const struct cli_apiglobal cli_globals[] = { |
52 | 53 |
/* Bytecode globals BEGIN */ |
... | ... |
@@ -131,7 +132,8 @@ const struct cli_apicall cli_apicalls[]={ |
131 | 131 |
{"trace_scope", 14, 7, 1}, |
132 | 132 |
{"trace_source", 14, 8, 1}, |
133 | 133 |
{"trace_op", 14, 9, 1}, |
134 |
- {"trace_value", 14, 10, 1} |
|
134 |
+ {"trace_value", 14, 10, 1}, |
|
135 |
+ {"trace_ptr", 14, 11, 1} |
|
135 | 136 |
/* Bytecode APIcalls END */ |
136 | 137 |
}; |
137 | 138 |
const cli_apicall_int2 cli_apicalls0[] = { |
... | ... |
@@ -150,6 +152,7 @@ const cli_apicall_pointer cli_apicalls1[] = { |
150 | 150 |
(cli_apicall_pointer)cli_bcapi_trace_scope, |
151 | 151 |
(cli_apicall_pointer)cli_bcapi_trace_source, |
152 | 152 |
(cli_apicall_pointer)cli_bcapi_trace_op, |
153 |
- (cli_apicall_pointer)cli_bcapi_trace_value |
|
153 |
+ (cli_apicall_pointer)cli_bcapi_trace_value, |
|
154 |
+ (cli_apicall_pointer)cli_bcapi_trace_ptr |
|
154 | 155 |
}; |
155 | 156 |
const unsigned cli_apicall_maxapi = sizeof(cli_apicalls)/sizeof(cli_apicalls[0]); |
... | ... |
@@ -44,5 +44,6 @@ uint32_t cli_bcapi_trace_scope(struct cli_bc_ctx *ctx, const const uint8_t*, uin |
44 | 44 |
uint32_t cli_bcapi_trace_source(struct cli_bc_ctx *ctx, const const uint8_t*, uint32_t); |
45 | 45 |
uint32_t cli_bcapi_trace_op(struct cli_bc_ctx *ctx, const const uint8_t*, uint32_t); |
46 | 46 |
uint32_t cli_bcapi_trace_value(struct cli_bc_ctx *ctx, const const uint8_t*, uint32_t); |
47 |
+uint32_t cli_bcapi_trace_ptr(struct cli_bc_ctx *ctx, const const uint8_t*, uint32_t); |
|
47 | 48 |
|
48 | 49 |
#endif |
... | ... |
@@ -136,6 +136,7 @@ struct cli_bc_ctx { |
136 | 136 |
bc_dbg_callback_trace trace; |
137 | 137 |
bc_dbg_callback_trace_op trace_op; |
138 | 138 |
bc_dbg_callback_trace_val trace_val; |
139 |
+ bc_dbg_callback_trace_ptr trace_ptr; |
|
139 | 140 |
unsigned trace_level; |
140 | 141 |
const char *directory; |
141 | 142 |
const char *file; |
... | ... |
@@ -241,6 +241,10 @@ private: |
241 | 241 |
return V; |
242 | 242 |
} |
243 | 243 |
V = Builder.CreateLoad(V); |
244 |
+ if (V->getType() != Ty && |
|
245 |
+ isa<PointerType>(V->getType()) && |
|
246 |
+ isa<PointerType>(Ty)) |
|
247 |
+ V = Builder.CreateBitCast(V, Ty); |
|
244 | 248 |
if (V->getType() != Ty) { |
245 | 249 |
errs() << operand << " "; |
246 | 250 |
V->dump(); |
... | ... |
@@ -425,8 +429,10 @@ public: |
425 | 425 |
assert(dest >= numArgs && dest < numLocals+numArgs && "Instruction destination out of range"); |
426 | 426 |
const Type *ETy = cast<PointerType>(cast<PointerType>(Values[dest]->getType())->getElementType())->getElementType(); |
427 | 427 |
Value *V = createGEP(Base, ETy, Start, End); |
428 |
- if (!V) |
|
428 |
+ if (!V) { |
|
429 |
+ errs() << "@ " << dest << "\n"; |
|
429 | 430 |
return false; |
431 |
+ } |
|
430 | 432 |
V = Builder.CreateBitCast(V, PointerType::getUnqual(ETy)); |
431 | 433 |
Store(dest, V); |
432 | 434 |
return true; |
... | ... |
@@ -630,6 +636,7 @@ public: |
630 | 630 |
Ty = PointerType::getUnqual(PointerType::getUnqual(Ty)); |
631 | 631 |
Value *Cast = Builder.CreateBitCast(GEP, Ty); |
632 | 632 |
Value *SpecialGV = Builder.CreateLoad(Cast); |
633 |
+ SpecialGV->setName("g"+Twine(g-_FIRST_GLOBAL)+"_"); |
|
633 | 634 |
Value *C[] = { |
634 | 635 |
ConstantInt::get(Type::getInt32Ty(Context), 0), |
635 | 636 |
ConstantInt::get(Type::getInt32Ty(Context), bc->globals[i][0]) |
... | ... |
@@ -640,8 +647,10 @@ public: |
640 | 640 |
Ty->dump(); |
641 | 641 |
llvm_report_error("(libclamav) unable to create fake global"); |
642 | 642 |
} |
643 |
- else if(GetElementPtrInst *GI = dyn_cast<GetElementPtrInst>(globals[i])) |
|
643 |
+ else if(GetElementPtrInst *GI = dyn_cast<GetElementPtrInst>(globals[i])) { |
|
644 | 644 |
GI->setIsInBounds(true); |
645 |
+ GI->setName("geped"+Twine(i)+"_"); |
|
646 |
+ } |
|
645 | 647 |
} |
646 | 648 |
} |
647 | 649 |
|
... | ... |
@@ -674,7 +683,6 @@ public: |
674 | 674 |
case OP_BC_SEXT: |
675 | 675 |
case OP_BC_TRUNC: |
676 | 676 |
case OP_BC_GEP1: |
677 |
- case OP_BC_GEP2: |
|
678 | 677 |
case OP_BC_GEPN: |
679 | 678 |
case OP_BC_STORE: |
680 | 679 |
case OP_BC_COPY: |
... | ... |
@@ -877,28 +885,20 @@ public: |
877 | 877 |
} |
878 | 878 |
case OP_BC_GEP1: |
879 | 879 |
{ |
880 |
- Value *V = convertOperand(func, inst, inst->u.binop[0]); |
|
881 |
- Value *Op = convertOperand(func, I32Ty, inst->u.binop[1]); |
|
880 |
+ const Type *SrcTy = mapType(inst->u.three[0]); |
|
881 |
+ Value *V = convertOperand(func, SrcTy, inst->u.three[1]); |
|
882 |
+ Value *Op = convertOperand(func, I32Ty, inst->u.three[2]); |
|
882 | 883 |
if (!createGEP(inst->dest, V, &Op, &Op+1)) |
883 | 884 |
return false; |
884 | 885 |
break; |
885 | 886 |
} |
886 |
- case OP_BC_GEP2: |
|
887 |
- { |
|
888 |
- std::vector<Value*> Idxs; |
|
889 |
- Value *V = convertOperand(func, inst, inst->u.three[0]); |
|
890 |
- Idxs.push_back(convertOperand(func, I32Ty, inst->u.three[1])); |
|
891 |
- Idxs.push_back(convertOperand(func, I32Ty, inst->u.three[2])); |
|
892 |
- if (!createGEP(inst->dest, V, Idxs.begin(), Idxs.end())) |
|
893 |
- return false; |
|
894 |
- break; |
|
895 |
- } |
|
896 | 887 |
case OP_BC_GEPN: |
897 | 888 |
{ |
898 | 889 |
std::vector<Value*> Idxs; |
899 |
- assert(inst->u.ops.numOps > 1); |
|
900 |
- Value *V = convertOperand(func, inst, inst->u.binop[0]); |
|
901 |
- for (unsigned a=1;a<inst->u.ops.numOps;a++) |
|
890 |
+ assert(inst->u.ops.numOps > 2); |
|
891 |
+ const Type *SrcTy = mapType(inst->u.ops.ops[0]); |
|
892 |
+ Value *V = convertOperand(func, SrcTy, inst->u.ops.ops[1]); |
|
893 |
+ for (unsigned a=2;a<inst->u.ops.numOps;a++) |
|
902 | 894 |
Idxs.push_back(convertOperand(func, I32Ty, inst->u.ops.ops[a])); |
903 | 895 |
if (!createGEP(inst->dest, V, Idxs.begin(), Idxs.end())) |
904 | 896 |
return false; |
... | ... |
@@ -14488,7 +14488,7 @@ $as_echo_n "checking for supported C++ compiler version... " >&6; } |
14488 | 14488 |
gxx_version=`${CXX} -dumpversion` || |
14489 | 14489 |
as_fn_error "Unable to get GNU C++ compiler version" "$LINENO" 5 |
14490 | 14490 |
case "${gxx_version}" in |
14491 |
- [0123].*) |
|
14491 |
+ [023].*) |
|
14492 | 14492 |
as_fn_error "C++ compiler too old (${gxx_version})" "$LINENO" 5 |
14493 | 14493 |
;; |
14494 | 14494 |
4.0.1*|4.1.[12]*) |
... | ... |
@@ -28,7 +28,7 @@ struct bytecode_metadata { |
28 | 28 |
char *targetExclude; |
29 | 29 |
}; |
30 | 30 |
|
31 |
-#define BC_FUNC_LEVEL 2 |
|
31 |
+#define BC_FUNC_LEVEL 3 |
|
32 | 32 |
#define BC_HEADER "ClamBC" |
33 | 33 |
|
34 | 34 |
enum bc_opcode { |
... | ... |
@@ -70,7 +70,6 @@ enum bc_opcode { |
70 | 70 |
OP_BC_CALL_API, |
71 | 71 |
OP_BC_COPY, |
72 | 72 |
OP_BC_GEP1, |
73 |
- OP_BC_GEP2, |
|
74 | 73 |
OP_BC_GEPN, |
75 | 74 |
OP_BC_STORE, |
76 | 75 |
OP_BC_LOAD, |
... | ... |
@@ -99,8 +98,8 @@ static const unsigned char operand_counts[] = { |
99 | 99 |
0, 0, |
100 | 100 |
/* OP_BC_COPY */ |
101 | 101 |
2, |
102 |
- /* OP_BC_GEP1, OP_BC_GEP2, OP_BC_GEPN, OP_BC_STORE, OP_BC_LOAD*/ |
|
103 |
- 2, 3, 0, 2, 1, |
|
102 |
+ /* OP_BC_GEP1, OP_BC_GEPN, OP_BC_STORE, OP_BC_LOAD*/ |
|
103 |
+ 3, 0, 2, 1, |
|
104 | 104 |
/* OP_MEM* */ |
105 | 105 |
3, 3, 3, 3, |
106 | 106 |
/* OP_BC_ISBIGENDIAN */ |
... | ... |
@@ -1984,8 +1984,7 @@ int cli_scanpe(cli_ctx *ctx, icon_groupset *iconset) |
1984 | 1984 |
|
1985 | 1985 |
|
1986 | 1986 |
/* yC 1.3 & variants */ |
1987 |
- |
|
1988 |
- if((DCONF & PE_CONF_YC) && nsections > 1 && |
|
1987 |
+ if((0 & DCONF & PE_CONF_YC) && nsections > 1 && |
|
1989 | 1988 |
(EC32(optional_hdr32.AddressOfEntryPoint) == exe_sections[nsections - 1].rva + 0x60)) { |
1990 | 1989 |
|
1991 | 1990 |
uint32_t ecx = 0; |
... | ... |
@@ -1,10 +1,10 @@ |
1 |
-ClamBCab`|``````|`akafp`clamcoincidencejb:82 |
|
1 |
+ClamBCac`|``````|`akafp`clamcoincidencejb:86 |
|
2 | 2 |
|
3 |
-Tedcaabjdebjdaaa`aacb`bbjdb`baacb`bb`bb`bebed |
|
4 |
-Eababaabhd|afdgefcgdg`c``abbid|afdgefcgdgac`` |
|
3 |
+Tedcaabfdebedebfdaaa`aacb`bbfdb`baacb`bb`bb`b |
|
4 |
+Eababaabid|afdgefcgdg`c``abbjd|afdgefcgdgac`` |
|
5 | 5 |
G`aa`@` |
6 |
-A`b`bLahbedabfd```b`b`aa`b`b`aa`b`b`Fajac |
|
7 |
-Bbfdaadb`@d@d``fb`aab`bacabbabHonnkm``odHm``oonnkdaaadeab`bacHhgfedcbadTaaadaaab |
|
6 |
+A`b`bLahbedabgd```b`b`aa`b`b`aa`b`b`Fajac |
|
7 |
+Bbgdaadbcbfd`@d@d``eb`aab`bacabbabHonnkm``odHm``oonnkdaaadeab`bacHhgfedcbadTaaadaaab |
|
8 | 8 |
Bb`baeabbaa`Honnkmjnmdaaafeab`baeHhgfedcbadb`bagoaafDm``odDmjnmdTcab`bag |
9 | 9 |
BTcab`bDmjnmdE |
10 | 10 |
Aab`bLabah`aa`b`b`Facaa |
... | ... |
@@ -1,11 +1,11 @@ |
1 |
-ClamBCab`|``c``a```|`bjaabp`clamcoincidencejb:326 |
|
1 |
+ClamBCac`|``c``a```|`bjaabp`clamcoincidencejb:326 |
|
2 | 2 |
Trojan.Foo.{A,B};Target:1;(((0|1|2)=42,2)|(3=10));EP+0:aabb;ffff;aaccee;f00d;dead |
3 | 3 |
Tedebieebheebgeebfeebeeebdeebbeebaeebadebcdaaa`aacb`bbadb`bdb`db`bcajbadbcebadbcebadbcebadbcebadbcecaab`bdagahdaeahdajahdabbaddabahdakah |
4 | 4 |
Eafaaafb`e|amcgefdgfgifbgegcgnfafmfef`` |
5 | 5 |
Gd```hbia`@`bieBdeBbgBofBjfBafBnfBnbBfdBofBof@`bheBad@`bheBbd@`bge@Ab@Ac`b`aAa`b`aC``a`bfeBedB`eBkbB`cBjcBafBafBbfBbf@`beeBffBffBffBff@`beeBffB`cB`cBdf@`bdeBafBafBcfBcfBefBef@`beeBdfBefBafBdf@`bbe@Ag@@AhAa@AiAc@AjAb@AkAd`bad@Ab`bad@Ac`bad@Ag`bad@Ah`bad@Ai`bad@Aj`bad@Ak`bcdAdD```h`bcdAcD```h`bcdAbD```h`bcdAaD```h`bcd@D```h` |
6 | 6 |
A`b`bLaeb`b`aa`aa`bad`b`b`Fahac |
7 |
-Bb`b`gbBda`aaaagab`b`AadTaaaaaaab |
|
7 |
+Bb`b`fbBda`aaaagab`b`AadTaaaaaaab |
|
8 | 8 |
Baaabeab`b`AbdbadacoaabAm`An`b`badabbafac@dTcab`b@d |
9 | 9 |
BTcab`b@dE |
10 | 10 |
A`aaLbcab`b`b`b`b`b`b`b`b`b`aa`aa`aa`aa`b`b`b`b`b`b`b`b`b`b`aa`aa`b`b`aa`aa`Fbdaaa |
11 |
-Bb`b`gbBha`b`baagbBga`b`babgbBfa`b`baca`aa`b`bada`acabaaaeeab`badBjbdaaaffab`bab@daaagfab`baa@daaahfab`b`@db`bai`aafb`baj`aagb`bak`aahb`bala`ajakb`bama`alaiaaaneab`bamAbdaaaok`anaeb`bb`agbBea`aabaaeab`bb`aAjdaabbal`aobaaTcaaabbaE |
|
11 |
+Bb`b`fbBha`b`baafbBga`b`babfbBfa`b`baca`aa`b`bada`acabaaaeeab`badBjbdaaaffab`bab@daaagfab`baa@daaahfab`b`@db`bai`aafb`baj`aagb`bak`aahb`bala`ajakb`bama`alaiaaaneab`bamAbdaaaok`anaeb`bb`afbBea`aabaaeab`bb`aAjdaabbal`aobaaTcaaabbaE |