1"use strict";(self.webpackChunkmifi_no=self.webpackChunkmifi_no||[]).push([[5284],{24018:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>c,contentTitle:()=>a,default:()=>p,frontMatter:()=>o,metadata:()=>t,toc:()=>d});var t=i(32783),s=i(74848),r=i(28453);const o={slug:"vipps-reverse-engineering",title:"Reverse engineering DNB VIPPS API by injecting Charles cert as pinned SSL certificate",authors:"mifi",tags:[]},a="Instructions",c={authorsImageUrls:[void 0]},d=[{value:"Links",id:"links",level:2}];function l(e){const n={a:"a",br:"br",code:"code",h1:"h1",h2:"h2",img:"img",li:"li",p:"p",strong:"strong",ul:"ul",...(0,r.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"UPDATE:"})," Outdated - ",(0,s.jsx)(n.a,{href:"/blog/sniffing-ssl-traffic-on-android-vipps-payment-app",children:"See new article"})]}),"\n",(0,s.jsx)(n.p,{children:"The VIPPS app is using API SSL certificate pinning to prevent MITM attacks, and the pinned certificate(s) is stored in the APK itself, so it can easily be replaced by our own generated Charles certificate. This allows sniffing the data going from the app to VIPPS servers."}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{src:"https://static.mifi.no/dist/2017/03/Screen-Shot-2017-03-05-at-22.33.17.jpg",alt:"charles"})}),"\n",(0,s.jsx)(n.p,{children:"First download the APK from somewhere (google it)"}),"\n",(0,s.jsxs)(n.p,{children:["Debuild APK",(0,s.jsx)(n.br,{}),"\n",(0,s.jsx)(n.code,{children:"apktool d no.dnb.vipps-1.6.5.apk"})]}),"\n",(0,s.jsxs)(n.p,{children:["Export Charles MITM SSL certificate by going to ",(0,s.jsx)(n.code,{children:"Help -> SSL Proxying -> Save Charles Root Certificate"})]}),"\n",(0,s.jsxs)(n.p,{children:["Inject Charles certificate into app",(0,s.jsx)(n.br,{}),"\n",(0,s.jsx)(n.code,{children:"cp charles-ssl-proxying-certificate.cer no.dnb.vipps-1.6.5.apk.out/res/raw/prod_priority_1.cer"})]}),"\n",(0,s.jsxs)(n.p,{children:["Put APK back together",(0,s.jsx)(n.br,{}),"\n",(0,s.jsx)(n.code,{children:"apktool b no.dnb.vipps-1.6.5.apk.out -o vipps-modified.apk"})]}),"\n",(0,s.jsxs)(n.p,{children:["Generate debug keystore for signing the new app",(0,s.jsx)(n.br,{}),"\n",(0,s.jsx)(n.code,{children:'echo y | keytool -genkey -v -keystore debug.keystore -storepass android -alias androiddebugkey -keypass android -keyalg RSA -keysize 2048 -validity 10000 -dname "cn=Mark Jones, ou=JavaSoft, o=Sun, c=US"'})]}),"\n",(0,s.jsxs)(n.p,{children:["Sign app with keystore",(0,s.jsx)(n.br,{}),"\n",(0,s.jsx)(n.code,{children:"apksigner sign --ks debug.keystore --out vipps-modified-signed.apk vipps-modified.apk"})]}),"\n",(0,s.jsxs)(n.p,{children:["Enter pw ",(0,s.jsx)(n.code,{children:"android"})]}),"\n",(0,s.jsxs)(n.p,{children:["Verify signing",(0,s.jsx)(n.br,{}),"\n",(0,s.jsx)(n.code,{children:"apksigner verify vipps-modified-signed.apk"})]}),"\n",(0,s.jsxs)(n.p,{children:["Install new APK to device",(0,s.jsx)(n.br,{}),"\n",(0,s.jsx)(n.code,{children:"adb install vipps-modified-signed.apk"})]}),"\n",(0,s.jsx)(n.p,{children:"Now just start Charles with SSL proxying enabled and set Charles (your computer's IP) as the proxy under WIFI settings on the Android device."}),"\n",(0,s.jsx)(n.h1,{id:"going-further---decompiling",children:"Going further - decompiling"}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.code,{children:"brew install dex2jar"})}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.code,{children:"d2j-dex2jar -f -o vipps.jar no.dnb.vipps-1.6.5.apk"})}),"\n",(0,s.jsx)(n.p,{children:"Use one of the following GUI tools for decompiling and looking at the code:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"https://github.com/skylot/jadx",children:"https://github.com/skylot/jadx"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"http://jd.benow.ca/",children:"http://jd.benow.ca/"})}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"None of them are perfect, and some code seems to fail decompiling in both."}),"\n",(0,s.jsx)(n.h2,{id:"links",children:"Links"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"http://stackoverflow.com/questions/21010367/how-to-decompile-an-apk-or-dex-file-on-android-platform",children:"http://stackoverflow.com/questions/21010367/how-to-decompile-an-apk-or-dex-file-on-android-platform"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"http://stackoverflow.com/questions/1249973/decompiling-dex-into-java-sourcecode",children:"http://stackoverflow.com/questions/1249973/decompiling-dex-into-java-sourcecode"})}),"\n"]})]})}function p(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(l,{...e})}):l(e)}},28453:(e,n,i)=>{i.d(n,{R:()=>o,x:()=>a});var t=i(96540);const s={},r=t.createContext(s);function o(e){const n=t.useContext(r);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:o(e.components),t.createElement(r.Provider,{value:n},e.children)}},32783:e=>{e.exports=JSON.parse('{"permalink":"/blog/vipps-reverse-engineering","editUrl":"https://github.com/mifi/mifi.no/tree/master/blog/2017-03-30-vipps-reverse-engineering.md","source":"@site/blog/2017-03-30-vipps-reverse-engineering.md","title":"Reverse engineering DNB VIPPS API by injecting Charles cert as pinned SSL certificate","description":"UPDATE: Outdated - See new article","date":"2017-03-30T00:00:00.000Z","tags":[],"readingTime":1.69,"hasTruncateMarker":true,"authors":[{"name":"Mikael Finstad","title":"mifi","url":"https://github.com/mifi","imageURL":"https://avatars.githubusercontent.com/u/402547?v=4","key":"mifi","page":null}],"frontMatter":{"slug":"vipps-reverse-engineering","title":"Reverse engineering DNB VIPPS API by injecting Charles cert as pinned SSL certificate","authors":"mifi","tags":[]},"unlisted":false,"prevItem":{"title":"Complete ICS / iCal / iCalendar parser / expander","permalink":"/blog/ical-expander"},"nextItem":{"title":"AWS Cogntio: Prevent email from being sent when email changed","permalink":"/blog/aws-cognito-prevent-email-verification"}}')}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.