Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/external/source/exploits/CVE-2017-13861/liboffsetfinder64/insn.cpp
Views: 11784
//1// insn.cpp2// liboffsetfinder643//4// Created by tihmstar on 09.03.18.5// Copyright © 2018 tihmstar. All rights reserved.6//78#define LOCAL_FILENAME "insn.cpp"910#include "all_liboffsetfinder.hpp"11#include "insn.hpp"12#include "exception.hpp"1314using namespace tihmstar::patchfinder64;1516insn::insn(segment_t segments, loc_t p, segtype segType) : _segments(segments), _segtype(segType){17std::sort(_segments.begin(),_segments.end(),[ ]( const text_t& lhs, const text_t& rhs){18return lhs.base < rhs.base;19});20if (_segtype != kText_and_Data) {21_segments.erase(std::remove_if(_segments.begin(), _segments.end(), [&](const text_t obj){22return (!obj.isExec) == (_segtype == kText_only);23}));24}25if (p == 0) {26p = _segments.at(0).base;27}28for (int i=0; i<_segments.size(); i++){29auto seg = _segments[i];30if ((loc_t)seg.base <= p && p < (loc_t)seg.base+seg.size){31_p = {p,i};32return;33}34}35throw out_of_range("initializing insn with out of range location");36}3738insn::insn(const insn &cpy, loc_t p){39_segments = cpy._segments;40_segtype = cpy._segtype;41if (p==0) {42_p = cpy._p;43}else{44for (int i=0; i<_segments.size(); i++){45auto seg = _segments[i];46if ((loc_t)seg.base <= p && p < (loc_t)seg.base+seg.size){47_p = {p,i};48return;49}50}51throw out_of_range("initializing insn with out of range location");52}53}5455insn &insn::operator++(){56_p.first+=4;57if (_p.first >=_segments[_p.second].base+_segments[_p.second].size){58if (_p.second+1 < _segments.size()) {59_p.first = _segments[++_p.second].base;60}else{61_p.first-=4;62throw out_of_range("overflow");63}64}65return *this;66}6768insn &insn::operator--(){69_p.first-=4;70if (_p.first < _segments[_p.second].base){71if (_p.second-1 >0) {72--_p.second;73_p.first = _segments[_p.second].base+_segments[_p.second].size;74}else{75_p.first+=4;76throw out_of_range("underflow");77}78}79return *this;80}8182insn insn::operator+(int i){83insn cpy(*this);84if (i>0) {85while (i--)86++cpy;87}else{88while (i++)89--cpy;90}91return cpy;92}9394insn insn::operator-(int i){95return this->operator+(-i);96}9798insn &insn::operator+=(int i){99if (i>0) {100while (i-->0)101this->operator++();102}else{103while (i++>0)104this->operator--();105}106return *this;107}108109insn &insn::operator-=(int i){110return this->operator+=(-i);111}112113insn &insn::operator=(loc_t p){114for (int i=0; i<_segments.size(); i++){115auto seg = _segments[i];116if ((loc_t)seg.base <= p && p < (loc_t)seg.base+seg.size){117_p = {p,i};118return *this;119}120}121throw out_of_range("initializing insn with out of range location");122}123124#pragma mark reference manual helpers125__attribute__((always_inline)) static int64_t signExtend64(uint64_t v, int vSize){126uint64_t e = (v & 1 << (vSize-1))>>(vSize-1);127for (int i=vSize; i<64; i++)128v |= e << i;129return v;130}131132__attribute__((always_inline)) static int highestSetBit(uint64_t x){133for (int i=63; i>=0; i--) {134if (x & ((uint64_t)1<<i))135return i;136}137return -1;138}139140__attribute__((always_inline)) static int lowestSetBit(uint64_t x){141for (int i=0; i<=63; i++) {142if (x & (1<<i))143return i;144}145return 64;146}147148__attribute__((always_inline)) static uint64_t replicate(uint64_t val, int bits){149uint64_t ret = val;150unsigned shift;151for (shift = bits; shift < 64; shift += bits) { // XXX actually, it is either 32 or 64152ret |= (val << shift);153}154return ret;155}156157__attribute__((always_inline)) static uint64_t ones(uint64_t n){158uint64_t ret = 0;159while (n--) {160ret <<=1;161ret |= 1;162}163return ret;164}165166__attribute__((always_inline)) static uint64_t ROR(uint64_t x, int shift, int len){167while (shift--) {168x |= (x & 1) << len;169x >>=1;170}171return x;172}173174static inline uint64_t ror(uint64_t elt, unsigned size)175{176return ((elt & 1) << (size-1)) | (elt >> 1);177}178179static inline uint64_t AArch64_AM_decodeLogicalImmediate(uint64_t val, unsigned regSize)180{181// Extract the N, imms, and immr fields.182unsigned N = (val >> 12) & 1;183unsigned immr = (val >> 6) & 0x3f;184unsigned imms = val & 0x3f;185unsigned i;186187// assert((regSize == 64 || N == 0) && "undefined logical immediate encoding");188// int len = 31 - countLeadingZeros((N << 6) | (~imms & 0x3f));189int len = highestSetBit( (uint64_t)((N<<6) | ((~imms) & 0b111111)) );190191// assert(len >= 0 && "undefined logical immediate encoding");192unsigned size = (1 << len);193unsigned R = immr & (size - 1);194unsigned S = imms & (size - 1);195// assert(S != size - 1 && "undefined logical immediate encoding");196uint64_t pattern = (1ULL << (S + 1)) - 1;197for (i = 0; i < R; ++i)198pattern = ror(pattern, size);199200// Replicate the pattern to fill the regSize.201while (size != regSize) {202pattern |= (pattern << size);203size *= 2;204}205206return pattern;207}208209__attribute__((always_inline)) static std::pair<int64_t, int64_t> DecodeBitMasks(uint64_t immN, uint8_t imms, uint8_t immr, bool immediate){210uint64_t tmask = 0, wmask = 0;211int8_t levels = 0; //6bit212213int len = highestSetBit( (uint64_t)((immN<<6) | ((~imms) & 0b111111)) );214assure(len != -1); //reserved value215levels = ones(len);216217assure(immediate && (imms & levels) != levels); //reserved value218219uint8_t S = imms & levels;220uint8_t R = immr & levels;221222uint8_t esize = 1 << len;223224uint8_t diff = S - R; // 6-bit subtract with borrow225226uint8_t d = (diff & ((1<<len)-1)) << 1;227228uint64_t welem = ones(S + 1);229uint64_t telem = ones(d + 1);230231uint64_t asd = ROR(welem, R, 32);232233wmask = replicate(ROR(welem, R, 32),esize);234tmask = replicate(telem,esize);235//#warning TODO incomplete function implementation!236return {wmask,tmask};237}238239#pragma mark bridges240uint64_t insn::pc(){241return (uint64_t)_p.first;242}243244uint32_t insn::value(){245return *(uint32_t*)(_p.first - _segments[_p.second].base + _segments[_p.second].map);246}247248uint64_t insn::doublevalue(){249return *(uint64_t*)(_p.first - _segments[_p.second].base + _segments[_p.second].map);250}251252#pragma mark static type determinition253254uint64_t insn::deref(segment_t segments, loc_t p){255return insn(segments, p, insn::kText_and_Data).doublevalue();256}257258bool insn::is_adrp(uint32_t i){259return BIT_RANGE(i, 24, 28) == 0b10000 && (i>>31);260}261262bool insn::is_adr(uint32_t i){263return BIT_RANGE(i, 24, 28) == 0b10000 && !(i>>31);264}265266bool insn::is_add(uint32_t i){267return BIT_RANGE(i, 24, 28) == 0b10001;268}269270bool insn::is_bl(uint32_t i){271return (i>>26) == 0b100101;272}273274bool insn::is_cbz(uint32_t i){275return BIT_RANGE(i, 24, 30) == 0b0110100;276}277278bool insn::is_ret(uint32_t i){279return ((0b11111 << 5) | i) == 0b11010110010111110000001111100000;280}281282bool insn::is_tbnz(uint32_t i){283return BIT_RANGE(i, 24, 30) == 0b0110111;284}285286bool insn::is_br(uint32_t i){287return ((0b11111 << 5) | i) == 0b11010110000111110000001111100000;288}289290bool insn::is_ldr(uint32_t i){291//#warning TODO recheck this mask292return (((i>>22) | 0b0100000000) == 0b1111100001 && ((i>>10) % 4)) || ((i>>22 | 0b0100000000) == 0b1111100101) || ((i>>23) == 0b00011000);293}294295bool insn::is_cbnz(uint32_t i){296return BIT_RANGE(i, 24, 30) == 0b0110101;297}298299bool insn::is_movk(uint32_t i){300return BIT_RANGE(i, 23, 30) == 0b11100101;301}302303bool insn::is_orr(uint32_t i){304return BIT_RANGE(i, 23, 30) == 0b01100100;305}306307bool insn::is_and(uint32_t i){308return BIT_RANGE(i, 23, 30) == 0b00100100; //immediate309// return BIT_RANGE(i, 24, 30) == 0b0001010; //shifted register310}311312bool insn::is_tbz(uint32_t i){313return BIT_RANGE(i, 24, 30) == 0b0110110;314}315316bool insn::is_ldxr(uint32_t i){317return (BIT_RANGE(i, 24, 29) == 0b001000) && (i >> 31) && BIT_AT(i, 22);318}319320bool insn::is_ldrb(uint32_t i){321return BIT_RANGE(i, 21, 31) == 0b00111000010 || //Immediate post/pre -indexed322BIT_RANGE(i, 22, 31) == 0b0011100101 || //Immediate unsigned offset323(BIT_RANGE(i, 21, 31) == 0b00111000011 && BIT_RANGE(i, 10, 11) == 0b10); //Register324}325326bool insn::is_str(uint32_t i){327//#warning TODO redo this! currently only recognises STR (immediate)328return (BIT_RANGE(i, 22, 29) == 0b11100100) && (i >> 31);329}330331bool insn::is_stp(uint32_t i){332//#warning TODO redo this! currently only recognises STR (immediate)333return (BIT_RANGE(i, 25, 30) == 0b010100) && !BIT_AT(i, 22);334}335336bool insn::is_movz(uint32_t i){337return (BIT_RANGE(i, 23, 30) == 0b10100101);338}339340bool insn::is_bcond(uint32_t i){341return (BIT_RANGE(i, 24, 31) == 0b01010100) && !BIT_AT(i, 4);342}343344bool insn::is_b(uint32_t i){345return (BIT_RANGE(i, 26, 31) == 0b000101);346}347348bool insn::is_nop(uint32_t i){349return (BIT_RANGE(i, 12, 31) == 0b11010101000000110010) && (0b11111 % (1<<5));350}351352353enum insn::type insn::type(){354uint32_t val = value();355if (is_adrp(val))356return adrp;357else if (is_adr(val))358return adr;359else if (is_add(val))360return add;361else if (is_bl(val))362return bl;363else if (is_cbz(val))364return cbz;365else if (is_ret(val))366return ret;367else if (is_tbnz(val))368return tbnz;369else if (is_br(val))370return br;371else if (is_ldr(val))372return ldr;373else if (is_cbnz(val))374return cbnz;375else if (is_movk(val))376return movk;377else if (is_orr(val))378return orr;379else if (is_and(val))380return and_;381else if (is_tbz(val))382return tbz;383else if (is_ldxr(val))384return ldxr;385else if (is_ldrb(val))386return ldrb;387else if (is_str(val))388return str;389else if (is_stp(val))390return stp;391else if (is_movz(val))392return movz;393else if (is_bcond(val))394return bcond;395else if (is_b(val))396return b;397else if (is_nop(val))398return nop;399400return unknown;401}402403enum insn::subtype insn::subtype(){404uint32_t i = value();405if (is_ldr(i)) {406if ((((i>>22) | (1 << 8)) == 0b1111100001) && BIT_RANGE(i, 10, 11) == 0b10)407return st_register;408else if (i>>31)409return st_immediate;410else411return st_literal;412}else if (is_ldrb(i)){413if (BIT_RANGE(i, 21, 31) == 0b00111000011 && BIT_RANGE(i, 10, 11) == 0b10)414return st_register;415else416return st_immediate;417}418return st_general;419}420421enum insn::supertype insn::supertype(){422switch (type()) {423case bl:424case cbz:425case cbnz:426case tbnz:427case bcond:428case b:429return sut_branch_imm;430431default:432return sut_general;433}434}435436#pragma mark register437438int64_t insn::imm(){439switch (type()) {440case unknown:441reterror("can't get imm value of unknown instruction");442break;443case adrp:444return ((pc()>>12)<<12) + signExtend64(((((value() % (1<<24))>>5)<<2) | BIT_RANGE(value(), 29, 30))<<12,32);445case adr:446return pc() + signExtend64((BIT_RANGE(value(), 5, 23)<<2) | (BIT_RANGE(value(), 29, 30)), 21);447case add:448return BIT_RANGE(value(), 10, 21) << (((value()>>22)&1) * 12);449case bl:450return pc() + (signExtend64(value() % (1<<26), 25) << 2); //untested451case cbz:452case cbnz:453case tbnz:454case bcond:455return pc() + (signExtend64(BIT_RANGE(value(), 5, 23), 19)<<2); //untested456case movk:457case movz:458return BIT_RANGE(value(), 5, 20);459case ldr:460if(subtype() != st_immediate){461reterror("can't get imm value of ldr that has non immediate subtype");462break;463}464if(BIT_RANGE(value(), 24, 25)){465// Unsigned Offset466return BIT_RANGE(value(), 10, 21) << (value()>>30);467}else{468// Signed Offset469return signExtend64(BIT_RANGE(value(), 12, 21), 9); //untested470}471case ldrb:472if (st_immediate) {473if (BIT_RANGE(value(), 22, 31) == 0b0011100101) { //unsigned474return BIT_RANGE(value(), 10, 21) << BIT_RANGE(value(), 30, 31);475}else{ //pre/post indexed476return BIT_RANGE(value(), 12, 20) << BIT_RANGE(value(), 30, 31);477}478}else{479reterror("ldrb must be st_immediate for imm to be defined!");480}481case str:482//#warning TODO rewrite this! currently only unsigned offset supported483// Unsigned Offset484return BIT_RANGE(value(), 10, 21) << (value()>>30);485case orr:486return DecodeBitMasks(BIT_AT(value(), 22),BIT_RANGE(value(), 10, 15),BIT_RANGE(value(), 16,21), true).first;487case and_:488{489int64_t val = DecodeBitMasks(BIT_AT(value(), 22),BIT_RANGE(value(), 10, 15),BIT_RANGE(value(), 16,21), true).first;490if (!BIT_AT(value(), 31))491val |= (((uint64_t)1<<32)-1) << 32;492return val;493}494case tbz:495return BIT_RANGE(value(), 5, 18);496case stp:497return signExtend64(BIT_RANGE(value(), 15, 21),7) << (2+(value()>>31));498case b:499return pc() + ((value() % (1<< 26))<<2);500default:501reterror("failed to get imm value");502break;503}504return 0;505}506507uint8_t insn::rd(){508switch (type()) {509case unknown:510reterror("can't get rd of unknown instruction");511break;512case adrp:513case adr:514case add:515case movk:516case orr:517case and_:518case movz:519return (value() % (1<<5));520521default:522reterror("failed to get rd");523break;524}525}526527uint8_t insn::rn(){528switch (type()) {529case unknown:530reterror("can't get rn of unknown instruction");531break;532case add:533case ret:534case br:535case orr:536case and_:537case ldxr:538case ldrb:539case str:540case ldr:541case stp:542return BIT_RANGE(value(), 5, 9);543544default:545reterror("failed to get rn");546break;547}548}549550uint8_t insn::rt(){551switch (type()) {552case unknown:553reterror("can't get rt of unknown instruction");554break;555case cbz:556case cbnz:557case tbnz:558case tbz:559case ldxr:560case ldrb:561case str:562case ldr:563case stp:564return (value() % (1<<5));565566default:567reterror("failed to get rt");568break;569}570}571572uint8_t insn::other(){573switch (type()) {574case unknown:575reterror("can't get other of unknown instruction");576break;577case tbz:578return ((value() >>31) << 5) | BIT_RANGE(value(), 19, 23);579case stp:580return BIT_RANGE(value(), 10, 14); //Rt2581case bcond:582return 0; //condition583case ldrb:584if (subtype() == st_register)585reterror("ERROR: unimplemented!");586else587reterror("ldrb must be st_register for this to be defined!");588default:589reterror("failed to get other");590break;591}592}593594#pragma mark cast operators595insn::operator void*(){596return (void*)(_p.first - _segments[_p.second].base + _segments[_p.second].map);597}598599insn::operator loc_t(){600return (loc_t)pc();601}602603insn::operator enum type(){604return type();605}606607#pragma mark additional functions608loc_t tihmstar::patchfinder64::find_literal_ref(segment_t segemts, loc_t pos, int ignoreTimes){609insn adrp(segemts);610uint8_t rd = 0xff;611uint64_t imm = 0;612613try {614for (;;++adrp){615if (adrp == insn::adr) {616if (adrp.imm() == (uint64_t)pos){617if (ignoreTimes) {618ignoreTimes--;619rd = 0xff;620imm = 0;621continue;622}623return (loc_t)adrp.pc();624}625}else if (adrp == insn::adrp) {626rd = adrp.rd();627imm = adrp.imm();628}else if (adrp == insn::add && rd == adrp.rd()){629if (imm + adrp.imm() == (int64_t)pos){630if (ignoreTimes) {631ignoreTimes--;632rd = 0xff;633imm = 0;634continue;635}636return (loc_t)adrp.pc();637}638}639}640} catch (std::out_of_range &e) {641return 0;642}643return 0;644}645646loc_t tihmstar::patchfinder64::find_rel_branch_source(insn bdst, bool searchUp, int ignoreTimes, int limit){647insn bsrc(bdst);648649bool hasLimit = (limit);650while (true) {651if (searchUp){652while ((--bsrc).supertype() != insn::sut_branch_imm){653if (hasLimit && !limit--) {654return 0;655}656}657}else{658while ((++bsrc).supertype() != insn::sut_branch_imm){659if (hasLimit && !limit--) {660return 0;661}662}663}664665if (bsrc.imm() == bdst.pc()) {666if (ignoreTimes) {667ignoreTimes--;668continue;669}670return (loc_t)bsrc.pc();671}672}673674//this return is never reached675return 0;676}677678679680